From e19afebb287128d88b7762c50dbf78c2fa91b218 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Fri, 22 Sep 2023 19:21:05 +0000 Subject: [PATCH] Merge pull request #131 from CertainLach/asciidocization --- --- /dev/null +++ b/README.adoc @@ -0,0 +1,88 @@ += jrsonnet + +image:https://img.shields.io/github/v/tag/CertainLach/jrsonnet?color=%23fb4934&label=latest%20release&style=for-the-badge[alt=release, link=https://github.com/CertainLach/jrsonnet/releases] +image:https://img.shields.io/github/license/CertainLach/jrsonnet?color=%2383a598&label=license&style=for-the-badge[alt=license, ./LICENSE] +image:https://img.shields.io/opencollective/all/jrsonnet?color=%238ec07c&style=for-the-badge[alt=opencollective, link=https://opencollective.com/jrsonnet] + +== What is it + +https://jsonnet.org/[Jsonnet] is a data templating language + +This Rust crate implements both jsonnet library and an alternative `jsonnet` executable based on it. +For more information see [bindings](#Bindings). + +== Install + +=== NixOS + +jrsonnet is packaged in nixpkgs and maintained by @CertainLach + +[source,sh] +---- +nix-env -iA nixpkgs.jrsonnet +---- + +=== MacOS + +jrsonnet is packaged to brew and maintained by @messense + +[source,sh] +---- +brew install jrsonnet +---- + +=== Windows/other linux distributions + +You can get latest build of jrsonnet in https://github.com/CertainLach/jrsonnet/releases[releases]. + +=== Build from sources + +jrsonnet should build on latest stable Rust version (probably on the oldest, but there is no MSRV policy provided) + +Debug build will work too, but it is much slower than release + +[source] +---- +cargo build --release +---- + +== Why? + +There already are multiple implementations of this standard implemented in different languages: + +* https://github.com/google/jsonnet[C++]; +* https://github.com/google/go-jsonnet/[Go]; +* https://github.com/databricks/sjsonnet[Scala]. + +This implementation shows performance better than all existing implementations. +For more information see link:./docs/benchmarks.md[benchmarks] + +Also, I wanted to experiment on new syntax features, and jrsonnet implements some of them. +For more information see link:./docs/features.adoc[features] + +In the end, it's always fun to implement something in Rust. + +== Bindings + +=== Rust + +image:https://img.shields.io/crates/v/jrsonnet-evaluator[alt=crates.io, link=https://crates.io/crates/jrsonnet-evaluator] +image:https://docs.rs/jrsonnet-evaluator/badge.svg[alt=docs.rs, link=https://docs.rs/jrsonnet-evaluator] + +Jrsonnet is written in rust itself, so just add it as dependency + +=== Python + +image:https://img.shields.io/pypi/v/rjsonnet[alt=crates.io, link=https://pypi.org/project/rjsonnet/] + +Bindings are created and maintained by @messense + +=== C/C++ + +Jrsonnet provides a standard `libjsonnet.so` shared library and should work as drop-in replacement for it + +=== Other + +WASM bingings are also available, Java bindings (Both JNI and WASM compiled to `.class`) are in progress + +See link:./bindings/[bindings] for more information. --- a/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# jrsonnet - -[![release](https://img.shields.io/github/v/tag/CertainLach/jrsonnet?color=%23fb4934&label=latest%20release&style=for-the-badge)](https://github.com/CertainLach/jrsonnet/releases) -[![license](https://img.shields.io/github/license/CertainLach/jrsonnet?color=%2383a598&label=license&style=for-the-badge)](/LICENSE) -[![opencollective](https://img.shields.io/opencollective/all/jrsonnet?color=%238ec07c&style=for-the-badge)](https://opencollective.com/jrsonnet) - -## What is it - -[Jsonnet](https://jsonnet.org/) is a data templating language - -This Rust crate implements both jsonnet library and an alternative `jsonnet` executable based on it. For more information see [bindings](#Bindings). - -## Install - -### NixOS - -jrsonnet is packaged in nixpkgs and maintained by @CertainLach - -```sh -nix-env -iA nixpkgs.jrsonnet -``` - -### MacOS - -jrsonnet is packaged to brew and maintained by @messense - -```sh -brew install jrsonnet -``` - -### Windows/other linux distributions - -You can get latest build of jrsonnet in [releases](https://github.com/CertainLach/jrsonnet/releases) - -### Build from sources - -jrsonnet should build on latest stable Rust version (probally on olders, but there is no MSRV policy provided) - -Debug build will work too, but it is much slower than release - -``` -cargo build --release -``` - -## Why? - -There already are multiple implementations of this standard implemented in different languages: [C++](https://github.com/google/jsonnet), [Go](https://github.com/google/go-jsonnet/), [Scala](https://github.com/databricks/sjsonnet). - -This implementation shows performance better than all existing implementations. For more information see [benchmarks](./docs/benchmarks.md). - -Also, I wanted to experiment on new syntax features, and jrsonnet implements some of them. For more information see [features](./docs/features.md) - -In the end, it's always fun to implement something in Rust. - -## Bindings - -### Rust - -[![crates.io](https://img.shields.io/crates/v/jrsonnet-evaluator)](https://crates.io/crates/jrsonnet-evaluator) -[![docs.rs](https://docs.rs/jrsonnet-evaluator/badge.svg)](https://docs.rs/jrsonnet-evaluator) - -Jrsonnet is written in rust itself, so just add it as dependency - -### Python - -[![crates.io](https://img.shields.io/pypi/v/rjsonnet)](https://pypi.org/project/rjsonnet/) - -Bindings are created and maintained by @messense - -### C/C++ - -Jrsonnet provides a standard `libjsonnet.so` shared library and should work as drop-in replacement for it - -### Other - -WASM bingings are also available, Java bindings (Both JNI and WASM compiled to .class) are in progress - -See [bindings](./bindings/) for more information. --- /dev/null +++ b/bindings/README.adoc @@ -0,0 +1,18 @@ += Native bindings + +Bindings are implemented in form of standard libjsonnet.so implementation. + +Headers are described in `c/libjsonnet.h`, this file is exact copy from `C` implementation of jsonnet, +plus additional jrsonnet-specific methods. + +Bindings should work as drop-in replacement for standard impl. + +== Building Linux .so library on MacOS + +You can use `cross-rs` to do so: + +[source,console] +---- +cargo install cross --git https://github.com/cross-rs/cross +cross build --release -p libjsonnet --target x86_64-unknown-linux-gnu +---- --- a/bindings/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Native bindings - -Bindings are implemented in form of standard libjsonnet.so implementation - -Headers are described in `c/libjsonnet.h`, this file is exact copy from `C` implementation of jsonnet, plus additional jrsonnet-specific methods - -Bindings should work as drop-in replacement for standard impl - -## Building Linux .so library on MacOS - -You can use `cross-rs` to do so: - -```console -cargo install cross --git https://github.com/cross-rs/cross -cross build --release -p libjsonnet --target x86_64-unknown-linux-gnu -``` --- /dev/null +++ b/bindings/jsonnet/README.adoc @@ -0,0 +1 @@ += libjsonnet.so implemented in Rust --- a/bindings/jsonnet/README.md +++ /dev/null @@ -1 +0,0 @@ -# libjsonnet.so implemented in Rust --- /dev/null +++ b/crates/jrsonnet-evaluator/README.adoc @@ -0,0 +1,3 @@ += jrsonnet-evaluator + +Interpreter for parsed jsonnet tree --- a/crates/jrsonnet-evaluator/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# jrsonnet-evaluator - -Interpreter for parsed jsonnet tree --- /dev/null +++ b/crates/jrsonnet-parser/README.adoc @@ -0,0 +1,3 @@ += jrsonnet-parser + +Parser for jsonnet language --- a/crates/jrsonnet-parser/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# jrsonnet-parser - -Parser for jsonnet language --- /dev/null +++ b/docs/features.adoc @@ -0,0 +1,180 @@ += Features + +Some features, which exists in jrsonnet, but not yet in other implementations. + +Any of those features may be enabled during build time using feature flags, i.e: `--features=exp-destruct`. + +== `exp-destruct` + +Destructuring assignment, upstream issue: https://github.com/google/jsonnet/issues/307 + +Destructuring object: + +[source,jsonnet] +---- +local {a: b} = obj; ... +// Same as +local b = obj.a; ... +---- + +Field name may be omitted: + +> However, field name omission looks off here, as currently jsonnet doesn't allows `local a = 1; {a}` +as a sugar for `local a = 1; {a: a}`, this causing asymmetry + +[source,jsonnet] +---- +local {a} = obj; ... +// Same as +local a = obj.a; ... +---- + +Rest of fields may be collected into another object: + +[source,jsonnet] +---- +local {a, ...rest} = obj; ... +---- + +And it is possible to set field defaults: + +[source,jsonnet] +---- +local {a = 1} = {}; + +a == 1 +---- + +Destructuring arrays: + +[source,jsonnet] +---- +local [a, b, c] = array; ... +---- + +Rest of fields in any position may be collected into other array: + +[source,jsonnet] +---- +local [...rest, a] = array; ... +local [a, ...rest] = array; ... +local [a, ...rest, b] = array; ... +---- + +In case of not needed fields there is `?` (because `_` is not reserved): + +[source,jsonnet] +---- +local [?, b, c] = ["a", "b", "c"]; ... +---- + +Recursive destructuring also works: + +[source,jsonnet] +---- +local {a: [{b: {c: d}}]} = {a:[{b:{c:5}}]}; d == 5 +---- + +Also, mutually recursive declaration works: + +[source,jsonnet] +---- +local + {a, b, c} = {a: y, b: c, c: x}, + {x, y, z} = {x: a, y: 2, z: b}; +z == 2 +---- + +This feature also works in function arguments: +> It is impossible to reference those parameters using named argument syntax + +[source,jsonnet] +---- +local myFun({a, b, c}) = a + b + c; + +myFun({a: 1, b: 2, c: 3}) +---- + +== `exp-preserve-order` + +Object field order preservation during manifestification, upstream issue: https://github.com/google/jsonnet/issues/903 + +This feature adds a new CLI argument: `--preserve-order`, +as well as additional `std.manifest*/std.objectFields*` standard library functions argument `preserve_order`. + +Using this argument, it is possible to have same field order in manifestification, as in declaration: + +[source,jsonnet] +---- +std.objectFields({c: 1, b: 2, a: 3}, preserve_order = false) == ['a', 'b', 'c'] # Fields were sorted +std.manifestJson({c: 1, b: 2, a: 3}, preserve_order = true) == ['c', 'b', 'a'] # Fields were serialized in declaration order +---- + +== `exp-object-iteration` + +Iteration over object fields in comprehensions, upstream issue: https://github.com/google/jsonnet/issues/543 + +This feature is not implemented as proposed in upstream, it only yields `[key, value]` arrays per element: + +[source,jsonnet] +---- +{ + [i[0] + '!']: i[1] + '!' + for i in { + a: 1, + b: 2, + c: 3, + } +} == { + 'a!': '1!', + 'b!': '2!', + 'c!': '3!', +} +---- + +However, it may be combined with `exp-destruct`, to implement syntax close to proposed: + +[source,jsonnet] +---- +{ + [k + '!']: v + '!' + for [k, v] in { + a: 1, + b: 2, + c: 3, + } +} == { + 'a!': '1!', + 'b!': '2!', + 'c!': '3!', +} +---- + +Unfortunately, there is no integration with the `exp-preserve-order` feature, +fields will still be iterated in sorted order, and using old syntax is required: + +[source,jsonnet] +---- +local obj = { + c: 3, + b: 2, + a: 1, +}; + +{ + [key + '!']: obj[key] + '!' + for key in std.objectFields(obj, preserve_order: true) +} == { + 'c!': '3!', + 'b!': '2!', + 'a!': '1!', +} +---- + +== `exp-null-coalescing` + +Provides a new operator and new indexing syntax sugar: + +`a ?? b` - equivalent to `if a == null then b else a` + +`a?.b`, `a?.['b']` - equivalent to `if a != null then std.get(a, 'b', null)` --- a/docs/features.md +++ /dev/null @@ -1,163 +0,0 @@ -# Features - -Some features, which exists in jrsonnet, but not yet in other implementations. - -Any of those features may be enabled during build time using feature flags, i.e: `--features=exp-destruct`. - -## `exp-destruct` - -Destructuring assignment, upstream issue: https://github.com/google/jsonnet/issues/307 - -Destructuring object: - -```jsonnet -local {a: b} = obj; ... -// Same as -local b = obj.a; ... -``` - -Field name may be omitted: - -> However, field name omission looks off here, as currently jsonnet doesn't allows `local a = 1; {a}` as a sugar for `local a = 1; {a: a}`, this causing asymmetry - -```jsonnet -local {a} = obj; ... -// Same as -local a = obj.a; ... -``` - -Rest of fields may be collected into another object: - -```jsonnet -local {a, ...rest} = obj; ... -``` - -And it is possible to set field defaults: - -```jsonnet -local {a = 1} = {}; - -a == 1 -``` - -Destructuring arrays: - -```jsonnet -local [a, b, c] = array; ... -``` - -Rest of fields in any position may be collected into other array: - -```jsonnet -local [...rest, a] = array; ... -local [a, ...rest] = array; ... -local [a, ...rest, b] = array; ... -``` - -In case of not needed fields there is `?` (because `_` is not reserved): - -```jsonnet -local [?, b, c] = ["a", "b", "c"]; ... -``` - -Recursive destructuring also works: - -```jsonnet -local {a: [{b: {c: d}}]} = {a:[{b:{c:5}}]}; d == 5 -``` - -Also mutually recursive declaration works: - -```jsonnet -local - {a, b, c} = {a: y, b: c, c: x}, - {x, y, z} = {x: a, y: 2, z: b}; -z == 2 -``` - -This feature also works in function arguments: -> It is impossible to reference those parameters using named argument syntax - -```jsonnet -local myFun({a, b, c}) = a + b + c; - -myFun({a: 1, b: 2, c: 3}) -``` - -## `exp-preserve-order` - -Object field order preservation during manifestification, upstream issue: https://github.com/google/jsonnet/issues/903 - -This feature adds a new CLI argument: `--preserve-order`, as well as additional `std.manifest*/std.objectFields*` standard library functions argument `preserve_order`. - -Using this argument, it is possible to have same field order in manifestification, as in declaration: - -```jsonnet -std.objectFields({c: 1, b: 2, a: 3}, preserve_order = false) == ['a', 'b', 'c'] # Fields were sorted -std.manifestJson({c: 1, b: 2, a: 3}, preserve_order = true) == ['c', 'b', 'a'] # Fields were serialized in declaration order -``` - -## `exp-object-iteration` - -Iteration over object fields in comprehensions, upstream issue: https://github.com/google/jsonnet/issues/543 - -This feature is not implemented as proposed in upstream, it only yields `[key, value]` arrays per element: - -```jsonnet -{ - [i[0] + '!']: i[1] + '!' - for i in { - a: 1, - b: 2, - c: 3, - } -} == { - 'a!': '1!', - 'b!': '2!', - 'c!': '3!', -} -``` - -However, it may be combined with `exp-destruct`, to implement syntax close to proposed: - -```jsonnet -{ - [k + '!']: v + '!' - for [k, v] in { - a: 1, - b: 2, - c: 3, - } -} == { - 'a!': '1!', - 'b!': '2!', - 'c!': '3!', -} -``` - -Unfortunately, there is no integration with the `exp-preserve-order` feature, fields will be still iterated in sorted order, and using old syntax is required: - -```jsonnet -local obj = { - c: 3, - b: 2, - a: 1, -}; - -{ - [key + '!']: obj[key] + '!' - for key in std.objectFields(obj, preserve_order: true) -} == { - 'c!': '3!', - 'b!': '2!', - 'a!': '1!', -} -``` - -## `exp-null-coalescing` - -Provides a new operator and new indexing syntax sugar: - -`a ?? b` - equivalent to `if a == null then b else a` - -`a?.b`, `a?.['b']` - equivalent to `if a != null then std.get(a, 'b', null)` -- gitstuff