NimYAML/doc/api.txt

111 lines
5.5 KiB
Plaintext

============
API Overview
============
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**.
.. image:: processing.svg
Intermediate Representation
===========================
The base of all YAML processing with NimYAML is the
`YamlStream <yaml.stream.html#YamlStream>`_. This is basically an iterator over
`YamlStreamEvent <yaml.stream.html#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 <yaml.serialization.html#load,,K>`_. 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 <yaml.parser.html#YamlParser>`_ object is needed.
This object stores some state while parsing that may be useful for error
reporting to the user. The `parse <yaml.parser.html#parse,YamlParser,Stream>`_
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 <yaml.serialization.html#dump,K,Stream,TagStyle,AnchorStyle,PresentationOptions>`_,
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 <yaml.serialization.html#represent,T,TagStyle,AnchorStyle>`_.
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 <yaml.presenter.html#present,YamlStream,Stream,TagLibrary,PresentationOptions>`_.
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 <yaml.dom.html#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.