Crate expry

Source
Expand description

expry is a fast schemaless binary format for data, with the ability for filtering and selecting parts of the information using expressions over the stored binary data. Expressions are compiled and optimized to bytecode, and during evaluation this bytecode is interpreted. JSON can be read into these data structures (using expry_parse_json). Because expry supports binary strings, not all expry values can be exported to JSON.

The following data types are supported:

  • null;
  • bool;
  • int64;
  • float;
  • double;
  • string (can contain binary data);
  • array;
  • object.

§Expressions

Expressions over binary objects are compiled to byte code, and can be transmitted over the network. This bytecode can be quickly evaluated, as the bytecode is optimized on the way the binary objects are stored on a low level. Keys inside objects are stored in an ordered way. If keys are not needed any more for evaluation of the current expression, they are permanently skipped.

  • Constants: null, false, true, numbers (including: 0x..., 0b..., ...f), strings with 'string' or "string" (including raw strings using r#"..."# with variable number of #, and hex strings with x'hex' and x"hex" and ).
  • Conditionals: if-then-else is support with the conditional (ternary) operator: cond ? then-part : else-part.
  • Object expression with { fields? }, with optional fields, individual fields separated by , (last entry can have a trailing ,):
    • fields can be name: expr with expr an expression or a primary data type (see above);
    • fields can be "name": expr with expr an expression or a primary data type (see above);
    • fields can be field (or field???), which copies the field from the this object;
    • fields can be (expr): expr to dynamically generate a field name (must be a string), e.g. { (somefield): 42, } (results in {x: 42} if somefield is "x").
  • Array expressions: [ expressions? ], with the optional expressions which are one or more expressions delimited by , (last entry can have a trailing ,). Example: [ 42+42, 37+37, ].
  • Arithmetic operators: +, -, *, /, ** (pow), % (mod).
  • Bitwise operators: |, &, ^ (xor), <<, >>
  • Logical operators: &&, ||, a ? b : c, ==, !=, >, >=, <, <=.
  • Special this field, to signify current object.
  • Array subscription: a[b] (array subscription) is supported to access indiviual elements in arrays
  • Length operator:
    • field.len() which result in the length of the field if it is a string (number of bytes), array (number of elements), or object (number of key-values).
  • String operators:
    • a .. b: concatenate strings a and b;
    • a *= b: true if string a contains with string b
    • a $= b: true if string a ends with string b
    • a ^= b: true if string a starts with string b
  • Field operators:
    • a.b.c.d is supported to access subfields;
    • a.get(b).get(c).get(d) is supported for dynamic subfields;
  • Error operators:
    • try operator: a ??? b: if there is an error during evaluation of a (like an undefined field, or division by zero). The shorthand a ??? is equivalent to a ??? null. Alternative syntax is try(a, b) and try(a).
    • not-null-else operator: a ?? b: if a is null, return b.
      • defined(x) and undefined(x): checks if value is (un)defined (such as a field lookup).
  • String methods:
    • .trim()
    • .lower()
    • .upper()
    • .hex()
    • .htmlescape()
    • .urlescape()
    • .sub(int[, int]) (third argument is length of resulting string, default the max integer value)
    • .basename()
    • .dirname()
    • .splitn(max, split_on) (split_on is the splitting string, max is the max number of elements in the resulting array), results in an array of strings
  • Type methods:
    • .tostring()
    • .toint()
    • .tofloat()
    • .todouble()
  • Methods taking a lambda function as argument. Lambda functions are specified as |x| expr with x the argument to the lambda function.
    • array.filter(lambda) filters array to only contain elements e where lambda(e) returns true (note that lambda should always return a boolean, otherwise the filter will fail)
    • array.map(lambda) maps array of elements e to an array of elements lambda(e)
    • array.sort_by_key(lambda) sorts array of elements e based on key lambda(e). Sorting of values is based on this type order: null, bool, int, float, double, string, array, object. If the type matches, the sorting is performed on the contents itself. Note that sorting of NaN floats will yield a dynamic error as this is not defined.
    • array.to_object(lamba) converts the array to an object, in which the key is the first value of the array returned by the lambda. The value is the second value of the array returned by the lambda.
    • array.to_map(lamba) creates a key - array of values object. The lambda returns [key, sort, value].

§User defined functions

During evaluation, there is also the possibility to add user defined functions. These user defined functions are only known at evaluation time, therefore there is no static type checking in place. Only runtime errors are generated if the number of arguments or type of arguments do not match.

§Easily convert custom data types to values

Using the From trait, custom data types can be easily converted to values, even if they are contained in data structures like Vec.

use expry::*;

struct Foo {
    foo: u32,
    bar: bool,
}

impl<'a> From<&'a Foo> for DecodedValue<'a> {
    fn from(v: &'a Foo) -> Self {
        value!({
            "foo": v.foo as i64,
            "bar": v.bar,
        })
    }
}

let foos = vec![
    Foo{foo:1,bar:true},
    Foo{foo:2,bar:false},
];
let encoded_value = value!({
  "foo": Foo{foo:1,bar:true},
  "foos": foos,
}).encode_to_vec();

Re-exports§

pub use crate::raw_utils::EncodingError;
pub use crate::memorypool::*;
pub use crate::raw_utils::*;
pub use crate::termcolors::*;
pub use crate::parser::*;
pub use crate::stringparser::*;

Modules§

macros
memorypool
parser
raw_utils
stringparser
termcolors

Macros§

clear
pool
rewind
value
Construct a expry::DecodedValue from a JSON-like literal.

Structs§

BytecodeRef
Reference to expry expression bytecode.
BytecodeVec
Self-contained expry expression bytecode.
CompileError
Easy
EncodedValueRef
Reference to a expry value.
EncodedValueVec
Self-contained expry value (in encoded form).
ExpryUntilNewLine
LazyDecodedArray
LazyDecodedObject
LexerError
NoCustomFuncs
An provided implementation of the custom function handler, that directly throws an error when invoked.

Enums§

CompileErrorDescription
DecodedValue
The central data type of expry. It is modelled similar to JSON, however, contains a couple of noteworthy differences.
EitherInputLookup
EvalError
ExpryType
ExpryTypeWarning
LazyDecodedValue
SimpleType
TypeError
ValueType
Described the different types of value expry supports.

Constants§

EXPRY_EMPTY_OBJECT
EXPRY_NULL

Traits§

CloneInMemoryScope
CustomFuncs
Trait that can be used to pass a custom user-provided function handler to expry eval functions.
InputLookup
Trait as input to expry_slice_func and expry_eval_func. This can provide lookup for not-yet encoded inputs to save on encoding/conversion time.

Functions§

expry_compile_error_format_console
Formats errors from compilation with a nice layout and underlines on the source lines, so that users can easily understand what to do.
expry_compile_error_format_html
Formats errors for HTML from compilation with a nice layout including the source lines, so that users can easily understand what to do.
expry_compile_error_format_short
expry_compile_expr
expry_compile_expr_typed
expry_compile_slice
Compiles an expression to bytecode that can quickly be evaluated using expry_eval and expry_slice.
expry_decode
Parses an encoded value to a decoded value.
expry_decode_lazy
Parses an encoded value to a value that can be easily decoded on the go.
expry_eval
Evaluate expression bytecode in the context of the given value, resulting in a decoded value.
expry_eval_func
Evaluate expression bytecode in the context of the given value, resulting in a decoded value. This version supports custom user defined functions.
expry_object_raw
Create an encoded object from individual sorted fields.
expry_object_to_type
expry_object_with_single_field
Creates an object with a single key-value pair inside. Expects value to be binary encoded.
expry_parse_expression
Parses an expry expression input to a decoded value. This involves compiling and evaluating the input. For more flexibility and re-use of compiled expression, see [expry_compile] and expry_eval.
expry_parse_json
Parses a JSON input to a decoded value.
expry_parse_object_type
expry_parse_type
expry_slice
Evaluate expression bytecode in the context of the given value, resulting in an encoded value.
expry_slice_func
Evaluate expression bytecode in the context of the given value, resulting in an encoded value. This version supports custom user defined functions.
expry_to_type
expry_to_type_lazy
expry_type_from_bytecode
expry_type_merge_objects
expry_type_warnings_to_string
key_empty
Returns empty key.
key_str
Calculates the key as used in this crate from a str. There is also a [u8] version.
key_u8
Calculates the key as used in this crate from an u8 slice. There is also a str version.
merge_objects_to_scope
Merges two encoded objects. Left hand side take preference (so the left hand side value of keys occuring in both is taken).
to_expry_array
to_expry_array_to_scope
to_expry_array_to_scope_header
to_expry_object
to_expry_object_in_scope

Type Aliases§

ConcreteInputLookup
DecodedArray
DecodedObject
Key
The keys in encoded expry objects.
KeyHash
Keys in Binary uses a simple 8-bit hash to speed up look ups.
StandardInputLookup
TypeObject