Made serialization part of yaml. Improved doc.

This commit is contained in:
Felix Krause 2016-02-12 20:44:38 +01:00
parent c6c13eb044
commit 325e3ec18f
7 changed files with 105 additions and 51 deletions

View File

@ -21,7 +21,6 @@ task serializationTests, "Run serialization tests":
task documentation, "Generate documentation":
exec "mkdir -p docout"
exec r"nim doc2 -o:docout/yaml.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml"
exec r"nim doc2 -o:docout/serialization.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml/serialization.nim"
exec r"nim rst2html -o:docout/index.html doc/index.txt"
exec "cp doc/docutils.css doc/style.css doc/testing.html doc/processing.svg docout"
setCommand "nop"

View File

@ -96,7 +96,9 @@
<g id="atomics" text-anchor="middle" transform="translate(0 90)">
<g id="represent" transform="translate(65 10)">
<use xlink:href="#atomic-right-long"/>
<text x="80" y="25" font-style="italic">represent</text>
<a xlink:href="yaml.html#represent,T,TagStyle,AnchorStyle" target="_top">
<text x="80" y="25" font-style="italic">represent</text>
</a>
</g>
<g id="serialize" transform="translate(235 10)">
@ -113,7 +115,9 @@
<g id="construct" transform="translate(65 120)">
<use xlink:href="#atomic-left-long"/>
<text x="80" y="35" font-style="italic">construct</text>
<a xlink:href="yaml.html#construct,YamlStream,T" target="_top">
<text x="80" y="35" font-style="italic">construct</text>
</a>
</g>
<g id="compose" transform="translate(235 120)">
@ -132,22 +136,30 @@
<g id="skipping-things" text-anchor="middle" transform="translate(0 50)">
<g id="skipping-represent" transform="translate(55 10)">
<use xlink:href="#skipping-right"/>
<text x="175" y="25" font-weight="bold">represent</text>
<a xlink:href="yaml.html#represent,T,TagStyle,AnchorStyle" target="_top">
<text x="175" y="25" font-weight="bold">represent</text>
</a>
</g>
<g id="skipping-construct" transform="translate(55 160)">
<use xlink:href="#skipping-left"/>
<text x="175" y="75" font-weight="bold">construct</text>
<a xlink:href="yaml.html#construct,YamlStream,T" target="_top">
<text x="175" y="75" font-weight="bold">construct</text>
</a>
</g>
</g>
<g id="whole-lines" text-anchor="middle" transform="translate(0 20)">
<g id="dump">
<use xlink:href="#whole-right"/>
<text x="325" y="25" font-style="italic" font-weight="bold">dump</text>
<a xlink:href="yaml.html#dump,K,Stream,PresentationStyle,TagStyle,AnchorStyle,int" target="_top">
<text x="325" y="25" font-style="italic" font-weight="bold">dump</text>
</a>
</g>
<g id="load" transform="translate(0 280)">
<use xlink:href="#whole-left"/>
<text x="325" y="25" font-style="italic" font-weight="bold">load</text>
<a xlink:href="yaml.html#load,Stream,K" target="_top">
<text x="325" y="25" font-style="italic" font-weight="bold">load</text>
</a>
</g>
</g>

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -67,7 +67,7 @@ html {
}
/* necessary for links to scroll to the right position */
dt:before {
dt a:before {
margin-top: -50px;
height: 50px;
content: ' ';

View File

@ -109,7 +109,6 @@ doc.file = """
<a href="testing.html">Testing Ground</a>
<span>API:</span>
<a href="yaml.html">Module yaml</a>
<a href="serialization.html">Module yaml.serialization</a>
</header>
<article id="documentId">
<div class="container">

View File

@ -1,41 +1,3 @@
import "../yaml"
import macros, strutils, streams, tables, json, hashes, typetraits
export yaml, streams, tables, json
type
TagStyle* = enum
tsNone, tsRootOnly, tsAll
AnchorStyle* = enum
asNone, asTidy, asAlways
RefNodeData* = object
p: pointer
count: int
anchor: AnchorId
ConstructionContext* = ref object
refs: Table[AnchorId, pointer]
SerializationContext* = ref object
refsList: seq[RefNodeData]
style: AnchorStyle
RawYamlStream* = iterator(): YamlStreamEvent {.raises: [].}
const
yTagNimInt8* = 100.TagId
yTagNimInt16* = 101.TagId
yTagNimInt32* = 102.TagId
yTagNimInt64* = 103.TagId
yTagNimUInt8* = 104.TagId
yTagNimUInt16* = 105.TagId
yTagNimUInt32* = 106.TagId
yTagNimUInt64* = 107.TagId
yTagNimFloat32* = 108.TagId
yTagNimFloat64* = 109.TagId
yTagNimChar* = 110.TagId
proc initRefNodeData(p: pointer): RefNodeData =
result.p = p
result.count = 1
@ -98,12 +60,16 @@ template presentTag(t: typedesc, ts: TagStyle): TagId =
if ts == tsNone: yTagQuestionMark else: yamlTag(t)
proc lazyLoadTag*(uri: string): TagId {.inline, raises: [].} =
## Internal function. Do not call explicitly.
try:
result = serializationTagLibrary.tags[uri]
except KeyError:
result = serializationTagLibrary.registerUri(uri)
macro serializable*(types: stmt): stmt =
## Macro for customizing serialization of user-defined types.
## Currently does not provide more features than just using the standard
## serialization procs. This will change in the future.
assert types.kind == nnkTypeSection
result = newStmtList(types)
for typedef in types.children:
@ -281,6 +247,7 @@ macro serializable*(types: stmt): stmt =
result.add(representProc)
proc safeTagUri*(id: TagId): string {.raises: [].} =
## Internal function. Do not call explicitly.
try:
let uri = serializationTagLibrary.uri(id)
if uri.len > 0 and uri[0] == '!':
@ -744,6 +711,7 @@ proc representObject*[O](value: ref O, ts: TagStyle, c: SerializationContext):
proc construct*[T](s: var YamlStream, target: var T)
{.raises: [YamlConstructionError, YamlStreamError].} =
## Construct a Nim value from a YAML stream.
var
context = newConstructionContext()
try:
@ -763,6 +731,7 @@ proc construct*[T](s: var YamlStream, target: var T)
proc load*[K](input: Stream, target: var K)
{.raises: [YamlConstructionError, IOError, YamlParserError].} =
## Load a Nim value from a YAML character stream.
var
parser = newYamlParser(serializationTagLibrary)
events = parser.parse(input)
@ -809,6 +778,7 @@ proc setAliasAnchor(a: var AnchorId, q: var seq[RefNodeData]) {.inline.} =
proc represent*[T](value: T, ts: TagStyle = tsRootOnly,
a: AnchorStyle = asTidy): YamlStream {.raises: [].} =
## Represent a Nim value as ``YamlStream``.
var
context = newSerializationContext(a)
objStream = iterator(): YamlStreamEvent =
@ -850,6 +820,7 @@ proc dump*[K](value: K, target: Stream, style: PresentationStyle = psDefault,
tagStyle: TagStyle = tsRootOnly,
anchorStyle: AnchorStyle = asTidy, indentationStep: int = 2)
{.raises: [YamlPresenterJsonError, YamlPresenterOutputError].} =
## Dump a Nim value as YAML character stream.
var events = represent(value, if style == psCanonical: tsAll else: tagStyle,
if style == psJson: asNone else: anchorStyle)
try:

View File

@ -1,4 +1,4 @@
import "../yaml/serialization"
import "../yaml"
import unittest
type

View File

@ -16,7 +16,8 @@
## automatically supported. While JSON is less readable than YAML,
## this enhances interoperability with other languages.
import streams, unicode, lexbase, tables, strutils, json, hashes, queues, macros
import streams, unicode, lexbase, tables, strutils, json, hashes, queues,
macros, typetraits
export streams, tables, json
when defined(yamlDebug):
@ -178,6 +179,51 @@ type
## flow style at all.
psMinimal, psCanonical, psDefault, psJson, psBlockOnly
TagStyle* = enum
## Whether object should be serialized with explicit tags.
##
## - ``tsNone``: No tags will be outputted unless necessary.
## - ``tsRootOnly``: A tag will only be outputted for the root tag and
## where necessary.
## - ``tsAll``: Tags will be outputted for every object.
tsNone, tsRootOnly, tsAll
AnchorStyle* = enum
## How ref object should be serialized.
##
## - ``asNone``: No anchors will be outputted. Values present at
## multiple places in the content that should be
## serialized will be fully serialized at every occurence.
## If the content is cyclic, this will lead to an
## endless loop!
## - ``asTidy``: Anchors will only be generated for objects that
## actually occur more than once in the content to be
## serialized. This is a bit slower and needs more memory
## than ``asAlways``.
## - ``asAlways``: Achors will be generated for every ref object in the
## content to be serialized, regardless of whether the
## object is referenced again afterwards
asNone, asTidy, asAlways
RefNodeData = object
p: pointer
count: int
anchor: AnchorId
ConstructionContext* = ref object
## Context information for the process of constructing Nim values from
## YAML.
refs: Table[AnchorId, pointer]
SerializationContext* = ref object
## Context information for the process of serializing YAML from Nim
## values.
refsList: seq[RefNodeData]
style: AnchorStyle
RawYamlStream* = iterator(): YamlStreamEvent {.raises: [].} ## \
## Stream of ``YamlStreamEvent``s returned by ``representObject`` procs.
YamlLoadingError* = object of Exception
## Base class for all exceptions that may be raised during the process
## of loading a YAML character stream.
@ -296,6 +342,18 @@ const
## yielded when no anchor was defined for a YAML node
yamlTagRepositoryPrefix* = "tag:yaml.org,2002:"
yTagNimInt8* = 100.TagId ## tag for Nim's ``int8``
yTagNimInt16* = 101.TagId ## tag for Nim's ``int16``
yTagNimInt32* = 102.TagId ## tag for Nim's ``int32``
yTagNimInt64* = 103.TagId ## tag for Nim's ``int64``
yTagNimUInt8* = 104.TagId ## tag for Nim's ``uint8``
yTagNimUInt16* = 105.TagId ## tag for Nim's ``uint16``
yTagNimUInt32* = 106.TagId ## tag for Nim's ``uint32``
yTagNimUInt64* = 107.TagId ## tag for Nim's ``uint64``
yTagNimFloat32* = 108.TagId ## tag for Nim's ``float32``
yTagNimFloat64* = 109.TagId ## tag for Nim's ``float64``
yTagNimChar* = 110.TagId ## tag for Nim's ``char``
# interface
@ -330,11 +388,25 @@ proc hash*(id: AnchorId): Hash {.borrow.}
proc initYamlStream*(backend: iterator(): YamlStreamEvent):
YamlStream {.raises: [].}
## Creates a new ``YamlStream`` that uses the given iterator as backend.
proc next*(s: var YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
## Get the next item of the stream. Requires ``finished(s) == true``.
## If the backend yields an exception, that exception will be encapsulated
## into a ``YamlStreamError``, which will be raised.
proc peek*(s: var YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
## Get the next item of the stream without advancing the stream.
## Requires ``finished(s) == true``. Handles exceptions of the backend like
## ``next()``.
proc `peek=`*(s: var YamlStream, value: YamlStreamEvent) {.raises: [].}
## Set the next item of the stream. Will replace a previously peeked item,
## if one exists.
proc finished*(s: var YamlStream): bool {.raises: [YamlStreamError].}
iterator items*(s: var YamlStream): YamlStreamEvent {.raises: [YamlStreamError].} =
## ``true`` if no more items are available in the stream. Handles exceptions
## of the backend like ``next()``.
iterator items*(s: var YamlStream): YamlStreamEvent
{.raises: [YamlStreamError].} =
## Iterate over all items of the stream. You may not use ``peek()`` on the
## stream while iterating.
if s.peeked:
s.peeked = false
yield s.cached
@ -463,4 +535,5 @@ include private.json
include private.presenter
include private.hints
include private.fastparse
include private.streams
include private.streams
include private.serialization