Other languages
===============

One of the aims of ryml is to provide an efficient YAML API for other
languages. JavaScript is fully available, and there is already a cursory
implementation for Python using only the low-level API. After ironing
out the general approach, other languages are likely to follow (all of
this is possible because we’re using `SWIG <http://www.swig.org/>`__,
which makes it easy to do so).


JavaScript
----------

A JavaScript+WebAssembly port is available, compiled through
`emscripten <https://emscripten.org/>`__.

Here's a quick example on how to configure, compile and run the tests
using `emcmake`:

.. code:: bash

   git clone --recursive https://github.com/biojppm/rapidyaml
   cd rapidyaml
   emcmake cmake -S . -B build/emscripten \
      -D RYML_DEV=ON \
      -D RYML_BUILD_TESTS=ON \
      -D RYML_BUILD_BENCHMARKS=OFF \
      -D RYML_TEST_SUITE=OFF \
      -D RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS=ON \
      -D CMAKE_BUILD_TYPE=Release \
      -D CMAKE_CXX_FLAGS='-s DISABLE_EXCEPTION_CATCHING=0'
   cmake --build build/emscripten --target ryml-test-run -j



Python
------

(Note that this is a work in progress. Additions will be made and
things will be changed.). The python port is using only the
index-based low-level API, which works with node indices and string
views. This API is very fast, but you may find it hard to use: it does not
build a python structure of dicts/seqs/scalars, and all the scalars
are string views into the source buffer, and not typed. With that
said, it is really fast, and once you have the tree, you can still walk
over the tree to create the native python structure. Have a look at
this `test file
<https://github.com/biojppm/rapidyaml/tree/v0.9.0/api/python/tests/test_readme.py>`__
to see how the python API works, and to judge whether it may be useful to your
case.

As for performance, in a `timeit benchmark <https://github.com/biojppm/rapidyaml/tree/v0.9.0/api/python/bm/parse_bm.py>`__ comparing against
`PyYaml <https://pyyaml.org/>`__ and
`ruamel.yaml <https://yaml.readthedocs.io/en/latest/>`__, ryml parses
quicker by generally 100x and up to 400x:

::

   +----------------------------------------+-------+----------+----------+-----------+
   | style_seqs_blck_outer1000_inner100.yml | count | time(ms) | avg(ms)  | avg(MB/s) |
   +----------------------------------------+-------+----------+----------+-----------+
   | parse:RuamelYamlParse                  |     1 | 4564.812 | 4564.812 |     0.173 |
   | parse:PyYamlParse                      |     1 | 2815.426 | 2815.426 |     0.280 |
   | parse:RymlParseInArena                 |    38 |  588.024 |   15.474 |    50.988 |
   | parse:RymlParseInArenaReuse            |    38 |  466.997 |   12.289 |    64.202 |
   | parse:RymlParseInPlace                 |    38 |  579.770 |   15.257 |    51.714 |
   | parse:RymlParseInPlaceReuse            |    38 |  462.932 |   12.182 |    64.765 |
   +----------------------------------------+-------+----------+----------+-----------+

(Note that the parse timings above are somewhat biased towards ryml,
because it does not perform any type conversions in Python-land: return
types are merely ``memoryviews`` to the source buffer, possibly copied
to the tree’s arena).

As for emitting, the improvement can be as high as 3000x:

::

   +----------------------------------------+-------+-----------+-----------+-----------+
   | style_maps_blck_outer1000_inner100.yml | count |  time(ms) |  avg(ms)  | avg(MB/s) |
   +----------------------------------------+-------+-----------+-----------+-----------+
   | emit_yaml:RuamelYamlEmit               |     1 | 18149.288 | 18149.288 |     0.054 |
   | emit_yaml:PyYamlEmit                   |     1 |  2683.380 |  2683.380 |     0.365 |
   | emit_yaml:RymlEmitToNewBuffer          |    88 |   861.726 |     9.792 |    99.976 |
   | emit_yaml:RymlEmitReuse                |    88 |   437.931 |     4.976 |   196.725 |
   +----------------------------------------+-------+-----------+-----------+-----------+
