From 8067815d8c32c0279343357612ee171de1700257 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sat, 1 Oct 2016 15:21:58 +0200 Subject: [PATCH] updated from devel --- api.html | 33 +++++++++++++++++-------- index.html | 19 ++++++++++++--- processing.svg | 50 +++++++++++++++++++------------------- serialization.html | 60 +++++++++++++++++++++++++--------------------- style.css | 33 +++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 65 deletions(-) diff --git a/api.html b/api.html index 62daf74..44fd3d4 100644 --- a/api.html +++ b/api.html @@ -6,7 +6,7 @@ - + @@ -19,7 +19,20 @@ Docs: Overview Serialization - Module yaml + + Modules + +
@@ -28,18 +41,18 @@

Introduction

NimYAML advocates parsing YAML input into native Nim types. Basic Nim library types like integers, floats and strings, as well as all tuples, enums and objects without private fields are supported out-of-the-box. Reference types are also supported, and NimYAML is able to detect if a reference occurs more than once and will serialize it accordingly. This means that NimYAML is able to dump and load potentially cyclic objects.

While loading into and dumping from native Nim types is the preferred way to use NimYAML, it also gives you complete control over each processing step, so that you can for example only use the parser and process its event stream yourself. The following diagram gives an overview of NimYAML's features based on the YAML processing pipeline. The items and terminology YAML defines is shown in italic, NimYAML's implementation name is shown in bold.

-

Intermediate Representation

The base of all YAML processing with NimYAML is the YamlStream. This is basically an iterator over YamlStreamEvent objects. Every proc that represents a single stage of the loading or dumping process will either take a YamlStream as input or return a YamlStream. Procs that implement the whole process in one step hide the YamlStream from the user. Every proc that returns a YamlStream guarantees that this stream is well-formed according to the YAML specification.

+

Intermediate Representation

The base of all YAML processing with NimYAML is the YamlStream. This is basically an iterator over YamlStreamEvent objects. Every proc that represents a single stage of the loading or dumping process will either take a YamlStream as input or return a YamlStream. Procs that implement the whole process in one step hide the YamlStream from the user. Every proc that returns a YamlStream guarantees that this stream is well-formed according to the YAML specification.

This stream-oriented API can efficiently be used to parse large amounts of data. The drawback is that errors in the input are only discovered while processing the YamlStream. If the YamlStream encounters an exception while producing the next event, it will throw a YamlStreamError which contains the original exception as parent. The caller should know which exceptions are possible as parents of YamlStream because they know the source of the YamlStream they provided.

-

Loading YAML

If you want to load YAML character data directly into a native Nim variable, you can use load. This is the easiest and recommended way to load YAML data. The following paragraphs will explain the steps involved.

-

For parsing, a YamlParser object is needed. This object stores some state while parsing that may be useful for error reporting to the user. The parse proc implements the YAML processing step of the same name. All syntax errors in the input character stream are processed by parse, which will raise a YamlParserError if it encounters a syntax error.

+

Loading YAML

If you want to load YAML character data directly into a native Nim variable, you can use load. This is the easiest and recommended way to load YAML data. This section gives an overview about how load is implemented. It is absolutely possible to reimplement the loading step using the low-level API.

+

For parsing, a YamlParser object is needed. This object stores some state while parsing that may be useful for error reporting to the user. The parse proc implements the YAML processing step of the same name. All syntax errors in the input character stream are processed by parse, which will raise a YamlParserError if it encounters a syntax error.

Transforming a YamlStream to a native YAML object is done via construct. It skips the compose step for efficiency reasons. As Nim is statically typed, you have to know the target type when you write your loading code. This is different from YAML APIs of dynamically typed languages. If you cannot know the type of your YAML input at compile time, you have to manually process the YamlStream to serve your needs.

-

Dumping YAML

Dumping is preferredly done with dump, which serializes a native Nim variable to a character stream. Like load, you can use the steps involved separately.

-

You transform a variable into a YamlStream with represent. Depending on the AnchorStyle you specify, this will transform ref variables with multiple instances into anchored elements and aliases (for asTidy and asAlways) or write the same element into all places it occurs (for asNone). Be aware that if you use asNone, the value you serialize might not round-trip.

-

Transforming a YamlStream into YAML character data is done with present. You can choose from multiple presentation styles. psJson is not able to process some features of YamlStream s, the other styles support all features and are guaranteed to round-trip to the same YamlStream if you parse the generated YAML character stream again.

+

Dumping YAML

Dumping is preferredly done with dump, which serializes a native Nim variable to a character stream. As with load, the following paragraph describes how dump is implemented using the low-level API.

+

A Nim value is transformed into a YamlStream with represent. Depending on the AnchorStyle you specify, this will transform ref variables with multiple instances into anchored elements and aliases (for asTidy and asAlways) or write the same element into all places it occurs (for asNone). Be aware that if you use asNone, the value you serialize might not round-trip.

+

Transforming a YamlStream into YAML character data is done with present. You can choose from multiple presentation styles. psJson is not able to process some features of YamlStream s, the other styles support all features and are guaranteed to round-trip to the same YamlStream if you parse the generated YAML character stream again.

-

The Document Object Model

Much like XML, YAML also defines a document object model. If you cannot or do not want to load a YAML character stream to native Nim types, you can instead load it into a YamlDocument. This YamlDocument can also be serialized into a YAML character stream. All tags will be preserved exactly as they are when transforming from and to a YamlDocument. The only important thing to remember is that when a value has no tag, it will get the non-specific tag "!" for quoted scalars and "?" for all other nodes.

+

The Document Object Model

Much like XML, YAML also defines a document object model. If you cannot or do not want to load a YAML character stream to native Nim types, you can instead load it into a YamlDocument. This YamlDocument can also be serialized into a YAML character stream. All tags will be preserved exactly as they are when transforming from and to a YamlDocument. The only important thing to remember is that when a value has no tag, it will get the non-specific tag "!" for quoted scalars and "?" for all other nodes.

While tags are preserved, anchors will be resolved during loading and re-added during serialization. It is allowed for a YamlNode to occur multiple times within a YamlDocument, in which case it will be serialized once and referred to afterwards via aliases.

The document object model is provided for completeness, but you are encouraged to use native Nim types as start- or endpoint instead. That may be significantly faster, as every YamlNode is allocated on the heap and subject to garbage collection.

@@ -49,7 +62,7 @@
diff --git a/index.html b/index.html index 7e98ba0..32a120b 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ - + @@ -19,7 +19,20 @@ Docs: Overview Serialization - Module yaml + + Modules + +
@@ -326,7 +339,7 @@
diff --git a/processing.svg b/processing.svg index 734b5d1..a312738 100644 --- a/processing.svg +++ b/processing.svg @@ -68,18 +68,18 @@ - + Application YAML - + Native Nim Types - + Representation @@ -87,7 +87,7 @@ YamlDocument - + Serialization @@ -95,7 +95,7 @@ YamlStream - + Presentation @@ -104,87 +104,87 @@ - + represent - + - + serialize - + - + present - + construct - + - + compose - + - + parse - + - + represent - + construct - + - + dump - - dumpDOM + + dumpDOM - + loadDOM - + load - + \ No newline at end of file diff --git a/serialization.html b/serialization.html index f774367..17c27e9 100644 --- a/serialization.html +++ b/serialization.html @@ -6,7 +6,7 @@ - + @@ -19,13 +19,26 @@ Docs: Overview Serialization - Module yaml + + Modules + +

Serialization Overview

-

Introduction

NimYAML tries hard to make transforming YAML characters streams to native Nim types and vice versa as easy as possible. In simple scenarios, you might not need anything else than the two procs dump and load. On the other side, the process should be as customizable as possible to allow the user to tightly control how the generated YAML character stream will look and how a YAML character stream is interpreted.

+

Introduction

NimYAML tries hard to make transforming YAML characters streams to native Nim types and vice versa as easy as possible. In simple scenarios, you might not need anything else than the two procs dump and load. On the other side, the process should be as customizable as possible to allow the user to tightly control how the generated YAML character stream will look and how a YAML character stream is interpreted.

An important thing to remember in NimYAML is that unlike in interpreted languages like Ruby, Nim cannot load a YAML character stream without knowing the resulting type beforehand. For example, if you want to load this piece of YAML:

%YAML 1.2
 --- !nim:system:seq(nim:system:int8)
@@ -35,7 +48,7 @@
 
 

Supported Types

NimYAML supports a growing number of types of Nim's system module and standard library, and it also supports user-defined object, tuple and enum types out of the box.

Important: NimYAML currently does not support polymorphism. This may be added in the future.

-

This also means that NimYAML is generally able to work with object, tuple and enum types defined in the standard library or a third-party library without further configuration.

+

This also means that NimYAML is generally able to work with object, tuple and enum types defined in the standard library or a third-party library without further configuration, given that all fields of the object are accessible at the code point where NimYAML's facilities are invoked.

Scalar Types

The following integer types are supported by NimYAML: int, int8, int16, int32, int64, uint8, uint16, uint32, uint64. Note that the int type has a variable size dependent on the target operation system. To make sure that it round-trips properly between 32-bit and 64-bit operating systems, it will be converted to an int32 during loading and dumping. This will raise an exception for values outside of the range int32.low .. int32.high! If you define the types you serialize yourself, always consider using an integer type with explicit length. The same goes for uint.

The floating point types float, float32 and float64 are also supported. There is currently no problem with float, because it is always a float64.

@@ -145,40 +158,33 @@ result.add(item) discard s.next()

representObject

proc representObject*(value: MyObject, ts: TagStyle = tsNone,
-                      c: SerializationContext): RawYamlStream {.raises: [].}

This proc should return an iterator over YamlStreamEvent which represents the type. Follow the following guidelines when implementing a custom representObject proc:

+ c: SerializationContext, tag: TagId): {.raises: [].}

This proc should push a list of tokens that represent the type into the serialization context via c.put. Follow the following guidelines when implementing a custom representObject proc:

  • You can use the helper template presentTag for outputting the tag.
  • -
  • Always output the first tag with a yAnchorNone. Anchors will be set automatically by ref type handling.
  • +
  • Always output the first token with a yAnchorNone. Anchors will be set automatically by ref type handling.
  • When outputting non-scalar types, you should use the representObject implementation of the child types, if possible.
  • -
  • Check if the given TagStyle equals tsRootOnly and if yes, change it to tsNone for the child values.
  • +
  • Always use the tag parameter as tag for the first token you generate.
  • Never write a representObject proc for ref types.

The following example for representing to a YAML scalar is the actual implementation of representing int types:

-
proc representObject*[T: uint8|uint16|uint32|uint64](
-        value: T, ts: TagStyle, c: SerializationContext):
-        RawYamlStream {.raises: [].} =
-    result = iterator(): YamlStreamEvent =
-        yield scalarEvent($value, presentTag(T, ts), yAnchorNone)

The following example for representing to a YAML non-scalar is the actual implementation of representing seq types:

-
proc representObject*[T](value: seq[T], ts: TagStyle,
-        c: SerializationContext): RawYamlStream {.raises: [].} =
-    result = iterator(): YamlStreamEvent =
-        let childTagStyle = if ts == tsRootOnly: tsNone else: ts
-        yield YamlStreamEvent(kind: yamlStartSequence,
-                              seqTag: presentTag(seq[T], ts),
-                              seqAnchor: yAnchorNone)
-        for item in value:
-            var events = representObject(item, childTagStyle, c)
-            while true:
-                let event = events()
-                if finished(events): break
-                yield event
-        yield YamlStreamEvent(kind: yamlEndSequence)
+
proc representObject*[T: int8|int16|int32|int64](value: T, ts: TagStyle,
+    c: SerializationContext, tag: TagId) {.raises: [].} =
+  ## represents an integer value as YAML scalar
+  c.put(scalarEvent($value, tag, yAnchorNone))

The following example for representing to a YAML non-scalar is the actual implementation of representing seq and set types:

+
proc representObject*[T](value: seq[T]|set[T], ts: TagStyle,
+    c: SerializationContext, tag: TagId) {.raises: [YamlStreamError].} =
+  ## represents a Nim seq as YAML sequence
+  let childTagStyle = if ts == tsRootOnly: tsNone else: ts
+  c.put(startSeqEvent(tag))
+  for item in value:
+    representChild(item, childTagStyle, c)
+  c.put(endSeqEvent())
diff --git a/style.css b/style.css index 2b93efb..3be9e52 100644 --- a/style.css +++ b/style.css @@ -18,6 +18,11 @@ header a { padding-right: 5px; } +header a.active { + background: #877 !important; + color: black !important; +} + header span { display: inline-block; line-height: 50px; @@ -27,6 +32,34 @@ header span { padding-right: 5px; } +header span a { + display: block; +} + +header span ul { + display: none; + position: absolute; + top: 100%; + list-style: none; + background: #111; + margin: 0; +} + +header span ul:after { + content: ""; clear: both; display: block; +} + +header span:hover > ul { + display: block; +} + +header span ul a { + font-size: smaller; + font-family: "Source Code Pro", Menlo, "Courier New", Courier, monospace; + padding: 0 10px; + line-height: 40px; +} + header a:link, header a:visited { background: inherit;