1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Results written straight into another representation (ADR 0017).
//!
//! [`Expression::evaluate`](crate::Expression::evaluate) returns its result as a
//! `serde_json::Value`. An application that needs the result in another representation (a host
//! language's objects, another JSON library) implements [`Builder`] for it and evaluates with
//! [`Expression::evaluate_source_to`](crate::Expression::evaluate_source_to) or
//! [`Expression::evaluate_document_to`](crate::Expression::evaluate_document_to), so that the
//! result is not built twice. It is the counterpart of [`input::Source`](crate::input::Source).
//!
//! The entry points give the result to a closure as an [`Output`], which
//! [`Output::write`] writes with a builder, within the size limit of a result
//! (`Options::max_result_size`) and the nesting limit, as `evaluate` converts it.
//!
//! ```
//! use jlens_core::output::Builder;
//! use jlens_core::{Bindings, Document, Expression, Options};
//!
//! /// Writes a result as compact text, with its keys in order.
//! struct Text;
//!
//! impl Builder for Text {
//! type Value = String;
//! type Array = Vec<String>;
//! type Object = Vec<String>;
//!
//! fn null(&mut self) -> String {
//! "null".into()
//! }
//! fn bool(&mut self, value: bool) -> String {
//! value.to_string()
//! }
//! fn number(&mut self, value: f64) -> String {
//! value.to_string()
//! }
//! fn string(&mut self, value: &str) -> String {
//! format!("{value:?}")
//! }
//! fn array(&mut self, len: usize) -> Vec<String> {
//! Vec::with_capacity(len)
//! }
//! fn push(&mut self, array: &mut Vec<String>, item: String) {
//! array.push(item);
//! }
//! fn end_array(&mut self, array: Vec<String>) -> String {
//! format!("[{}]", array.join(","))
//! }
//! fn object(&mut self, len: usize) -> Vec<String> {
//! Vec::with_capacity(len)
//! }
//! fn insert(&mut self, object: &mut Vec<String>, key: &str, value: String) {
//! object.push(format!("{key:?}:{value}"));
//! }
//! fn end_object(&mut self, object: Vec<String>) -> String {
//! format!("{{{}}}", object.join(","))
//! }
//! }
//!
//! let document = Document::new(&serde_json::json!({"items": [{"price": 2}, {"price": 3.5}]}));
//! let expr = Expression::compile("{'total': $sum(items.price), 'none': $x}").unwrap();
//! let result = expr.evaluate_document_to(&document, &Bindings::new(), &Options::default(), |out| {
//! out.write(&mut Text)
//! });
//! assert_eq!(result.unwrap().as_deref(), Some(r#"{"total":5.5}"#));
//! ```
use crateResult;
use crate;
/// Builds a result in another representation, one value at a time (see the
/// [module](self) documentation).
///
/// The values of a result are written in order, depth first: an array is started with
/// [`array`](Builder::array), given its items with [`push`](Builder::push) and finished with
/// [`end_array`](Builder::end_array); an object likewise, with each field given with its key.
/// Undefined values and functions are left out of objects and written as `null` in arrays, as
/// `JSON.stringify` does.
///
/// The methods cannot fail. A builder whose representation can fail (a host language that runs
/// out of memory) keeps its first failure, returns any value of its type, and reports the failure
/// once the evaluation has returned.
/// The result of an evaluation, not written yet. [`Output::write`] writes it.