async_jsonata_rust/lib.rs
1#![allow(clippy::approx_constant)]
2#![allow(clippy::cast_abs_to_unsigned)]
3#![allow(clippy::get_first)]
4#![allow(clippy::manual_range_contains)]
5#![allow(clippy::module_inception)]
6#![allow(clippy::needless_borrow)]
7#![allow(clippy::result_large_err)]
8#![allow(clippy::type_complexity)]
9#![allow(clippy::unnecessary_map_or)]
10
11//! Async-first JSONata crate for Rust.
12//!
13//! This crate exposes a stable public surface focused on:
14//! - JSONata parsing (`Parser`, `Expression`)
15//! - function registry management (`FunctionRegistry`)
16//! - async custom functions (`types::JsonCallable` / `types::JsonataCallable`)
17//! - evaluator facade (`Evaluator`, runtime parity in progress)
18//!
19//! JSONata language reference:
20//! - <https://docs.jsonata.org/overview>
21//! - <https://docs.jsonata.org/path-operators>
22//! - <https://docs.jsonata.org/programming>
23//!
24//! # Quick Start
25//! ```rust
26//! use async_jsonata_rust::Parser;
27//!
28//! let parser = Parser::new();
29//! let expression = parser.parse("Account.Order[0].Product")?;
30//! assert_eq!(expression.ast()["type"], "path");
31//! # Ok::<(), async_jsonata_rust::Error>(())
32//! ```
33//!
34//! # JSONata syntax
35//! `async_jsonata_rust` follows JSONata syntax from the official docs and upstream test-suite.
36//! Parser support is production-oriented, while evaluator parity is declared separately in
37//! `docs/compatibility.md` and crate README.
38//!
39//! # Async functions
40//! ```rust
41//! use std::any::Any;
42//! use std::sync::Arc;
43//!
44//! use futures::executor::block_on;
45//! use futures::future::BoxFuture;
46//! use async_jsonata_rust::functions::core;
47//! use async_jsonata_rust::types::{FunctionContext, JsonArray, JsonCallable, JsonError, JsonFunction, JsonValue};
48//!
49//! #[derive(Clone)]
50//! struct DoubleCallable;
51//!
52//! impl JsonCallable for DoubleCallable {
53//! fn call(&self, _ctx: FunctionContext, args: Vec<JsonValue>) -> BoxFuture<'static, Result<JsonValue, JsonError>> {
54//! let input = args.first().cloned().unwrap_or(JsonValue::Undefined);
55//! Box::pin(async move {
56//! if let JsonValue::Number(value) = input {
57//! return Ok(JsonValue::Number(value * 2.0));
58//! }
59//! Ok(JsonValue::Undefined)
60//! })
61//! }
62//!
63//! fn arity(&self) -> Option<usize> {
64//! Some(1)
65//! }
66//!
67//! fn as_any(&self) -> &(dyn Any + Send + Sync) {
68//! self
69//! }
70//! }
71//!
72//! let input = JsonValue::Array(JsonArray::new(
73//! vec![JsonValue::Number(1.0), JsonValue::Number(2.0)],
74//! true,
75//! false,
76//! ));
77//! let func = JsonValue::Function(JsonFunction::new(Arc::new(DoubleCallable)));
78//! let out = block_on(core::map(FunctionContext::empty(), input, func)).unwrap();
79//! assert!(matches!(out, JsonValue::Array(_)));
80//! ```
81//!
82//! # Errors
83//! Stable APIs return unified [`Error`] with JSONata-style code (`S0201`, `D3040`, ...)
84//! and structured context fields.
85
86pub mod api;
87pub mod error;
88pub mod functions;
89pub mod parser;
90pub mod registry;
91pub mod types;
92
93pub use api::{Evaluator, Expression, FunctionRegistry, Parser};
94pub use error::Error;
95
96pub use parser::{
97 parse_expression, AstNode, Parser as LowLevelParser, ParserError, Token, TokenKind, Tokenizer,
98};
99pub use registry::{create_builtin_registry, lookup_builtin};
100pub use types::{
101 JsonArray, JsonCallable, JsonError, JsonFunction, JsonObject, JsonValue, JsonataArray,
102 JsonataCallable, JsonataFocus, JsonataFunction, JsonataObject, JsonataValue, NativeRef,
103 NativeType,
104};