Line data Source code
1 : //! A JSON serialization lib, designed for more flexibility than `serde_json` offers.
2 : //!
3 : //! Features:
4 : //!
5 : //! ## Dynamic construction
6 : //!
7 : //! Sometimes you have dynamic values you want to serialize, that are not already in a serde-aware model like a struct or a Vec etc.
8 : //! To achieve this with serde, you need to implement a lot of different traits on a lot of different new-types.
9 : //! Because of this, it's often easier to give-in and pull all the data into a serde-aware model (`serde_json::Value` or some intermediate struct),
10 : //! but that is often not very efficient.
11 : //!
12 : //! This crate allows full control over the JSON encoding without needing to implement any extra traits. Just call the
13 : //! relevant functions, and it will guarantee a correctly encoded JSON value.
14 : //!
15 : //! ## Async construction
16 : //!
17 : //! Similar to the above, sometimes the values arrive asynchronously. Often collecting those values in memory
18 : //! is more expensive than writing them as JSON, since the overheads of `Vec` and `String` is much higher, however
19 : //! there are exceptions.
20 : //!
21 : //! Serializing to JSON all in one go is also more CPU intensive and can cause lag spikes,
22 : //! whereas serializing values incrementally spreads out the CPU load and reduces lag.
23 : //!
24 : //! ## Examples
25 : //!
26 : //! To represent the following JSON as a compact string
27 : //!
28 : //! ```json
29 : //! {
30 : //! "results": {
31 : //! "rows": [
32 : //! {
33 : //! "id": 1,
34 : //! "value": null
35 : //! },
36 : //! {
37 : //! "id": 2,
38 : //! "value": "hello"
39 : //! }
40 : //! ]
41 : //! }
42 : //! }
43 : //! ```
44 : //!
45 : //! We can use the following code:
46 : //!
47 : //! ```
48 : //! // create the outer object
49 : //! let s = json::value_to_string!(|v| json::value_as_object!(|v| {
50 : //! // create an entry with key "results" and start an object value associated with it.
51 : //! let results = v.key("results");
52 : //! json::value_as_object!(|results| {
53 : //! // create an entry with key "rows" and start an list value associated with it.
54 : //! let rows = results.key("rows");
55 : //! json::value_as_list!(|rows| {
56 : //! // create a list entry and start an object value associated with it.
57 : //! let row = rows.entry();
58 : //! json::value_as_object!(|row| {
59 : //! // add entry "id": 1
60 : //! row.entry("id", 1);
61 : //! // add entry "value": null
62 : //! row.entry("value", json::Null);
63 : //! });
64 : //!
65 : //! // create a list entry and start an object value associated with it.
66 : //! let row = rows.entry();
67 : //! json::value_as_object!(|row| {
68 : //! // add entry "id": 2
69 : //! row.entry("id", 2);
70 : //! // add entry "value": "hello"
71 : //! row.entry("value", "hello");
72 : //! });
73 : //! });
74 : //! });
75 : //! }));
76 : //!
77 : //! assert_eq!(s, r#"{"results":{"rows":[{"id":1,"value":null},{"id":2,"value":"hello"}]}}"#);
78 : //! ```
79 :
80 : mod macros;
81 : mod str;
82 : mod value;
83 :
84 : pub use value::{Null, ValueEncoder};
85 :
86 : #[must_use]
87 : /// Serialize a single json value.
88 : pub struct ValueSer<'buf> {
89 : buf: &'buf mut Vec<u8>,
90 : start: usize,
91 : }
92 :
93 : impl<'buf> ValueSer<'buf> {
94 : /// Create a new json value serializer.
95 40 : pub fn new(buf: &'buf mut Vec<u8>) -> Self {
96 40 : Self { buf, start: 0 }
97 40 : }
98 :
99 : /// Borrow the underlying buffer
100 2 : pub fn as_buffer(&self) -> &[u8] {
101 2 : self.buf
102 2 : }
103 :
104 : #[inline]
105 94 : pub fn value(self, e: impl ValueEncoder) {
106 94 : e.encode(self);
107 18 : }
108 :
109 : /// Write raw bytes to the buf. This must be already JSON encoded.
110 : #[inline]
111 31 : pub fn write_raw_json(self, data: &[u8]) {
112 31 : self.buf.extend_from_slice(data);
113 31 : self.finish();
114 5 : }
115 :
116 : /// Start a new object serializer.
117 : #[inline]
118 3 : pub fn object(self) -> ObjectSer<'buf> {
119 3 : ObjectSer::new(self)
120 3 : }
121 :
122 : /// Start a new list serializer.
123 : #[inline]
124 2 : pub fn list(self) -> ListSer<'buf> {
125 2 : ListSer::new(self)
126 2 : }
127 :
128 : /// Finish the value ser.
129 : #[inline]
130 148 : fn finish(self) {
131 : // don't trigger the drop handler which triggers a rollback.
132 : // this won't cause memory leaks because `ValueSet` owns no allocations.
133 148 : std::mem::forget(self);
134 26 : }
135 : }
136 :
137 : impl Drop for ValueSer<'_> {
138 1 : fn drop(&mut self) {
139 1 : self.buf.truncate(self.start);
140 1 : }
141 : }
142 :
143 : #[must_use]
144 : /// Serialize a json object.
145 : pub struct ObjectSer<'buf> {
146 : value: ValueSer<'buf>,
147 : start: usize,
148 : }
149 :
150 : impl<'buf> ObjectSer<'buf> {
151 : /// Start a new object serializer.
152 : #[inline]
153 5 : pub fn new(value: ValueSer<'buf>) -> Self {
154 5 : value.buf.push(b'{');
155 5 : let start = value.buf.len();
156 5 : Self { value, start }
157 5 : }
158 :
159 : /// Borrow the underlying buffer
160 0 : pub fn as_buffer(&self) -> &[u8] {
161 0 : self.value.as_buffer()
162 0 : }
163 :
164 : /// Start a new object entry with the given string key, returning a [`ValueSer`] for the associated value.
165 : #[inline]
166 8 : pub fn key(&mut self, key: impl KeyEncoder) -> ValueSer<'_> {
167 8 : key.write_key(self)
168 8 : }
169 :
170 : /// Write an entry (key-value pair) to the object.
171 : #[inline]
172 6 : pub fn entry(&mut self, key: impl KeyEncoder, val: impl ValueEncoder) {
173 6 : self.key(key).value(val);
174 6 : }
175 :
176 : #[inline]
177 8 : fn entry_inner(&mut self, f: impl FnOnce(&mut Vec<u8>)) -> ValueSer<'_> {
178 : // track before the separator so we the value is rolled back it also removes the separator.
179 8 : let start = self.value.buf.len();
180 :
181 : // push separator if necessary
182 8 : if self.value.buf.len() > self.start {
183 3 : self.value.buf.push(b',');
184 5 : }
185 : // push key
186 8 : f(self.value.buf);
187 : // push value separator
188 8 : self.value.buf.push(b':');
189 :
190 : // return value writer.
191 8 : ValueSer {
192 8 : buf: self.value.buf,
193 8 : start,
194 8 : }
195 8 : }
196 :
197 : /// Reset the buffer back to before this object was started.
198 : #[inline]
199 1 : pub fn rollback(self) -> ValueSer<'buf> {
200 : // Do not fully reset the value, only reset it to before the `{`.
201 : // This ensures any `,` before this value are not clobbered.
202 1 : self.value.buf.truncate(self.start - 1);
203 1 : self.value
204 1 : }
205 :
206 : /// Finish the object ser.
207 : #[inline]
208 4 : pub fn finish(self) {
209 4 : self.value.buf.push(b'}');
210 4 : self.value.finish();
211 4 : }
212 : }
213 :
214 : pub trait KeyEncoder {
215 : fn write_key<'a>(self, obj: &'a mut ObjectSer) -> ValueSer<'a>;
216 : }
217 :
218 : #[must_use]
219 : /// Serialize a json object.
220 : pub struct ListSer<'buf> {
221 : value: ValueSer<'buf>,
222 : start: usize,
223 : }
224 :
225 : impl<'buf> ListSer<'buf> {
226 : /// Start a new list serializer.
227 : #[inline]
228 45 : pub fn new(value: ValueSer<'buf>) -> Self {
229 45 : value.buf.push(b'[');
230 45 : let start = value.buf.len();
231 45 : Self { value, start }
232 6 : }
233 :
234 : /// Borrow the underlying buffer
235 2 : pub fn as_buffer(&self) -> &[u8] {
236 2 : self.value.as_buffer()
237 2 : }
238 :
239 : /// Write an value to the list.
240 : #[inline]
241 1 : pub fn push(&mut self, val: impl ValueEncoder) {
242 1 : self.entry().value(val);
243 1 : }
244 :
245 : /// Start a new value entry in this list.
246 : #[inline]
247 101 : pub fn entry(&mut self) -> ValueSer<'_> {
248 : // track before the separator so we the value is rolled back it also removes the separator.
249 101 : let start = self.value.buf.len();
250 :
251 : // push separator if necessary
252 101 : if self.value.buf.len() > self.start {
253 56 : self.value.buf.push(b',');
254 56 : }
255 :
256 : // return value writer.
257 101 : ValueSer {
258 101 : buf: self.value.buf,
259 101 : start,
260 101 : }
261 11 : }
262 :
263 : /// Reset the buffer back to before this object was started.
264 : #[inline]
265 1 : pub fn rollback(self) -> ValueSer<'buf> {
266 : // Do not fully reset the value, only reset it to before the `[`.
267 : // This ensures any `,` before this value are not clobbered.
268 1 : self.value.buf.truncate(self.start - 1);
269 1 : self.value
270 1 : }
271 :
272 : /// Finish the object ser.
273 : #[inline]
274 43 : pub fn finish(self) {
275 43 : self.value.buf.push(b']');
276 43 : self.value.finish();
277 4 : }
278 : }
279 :
280 : #[cfg(test)]
281 : mod tests {
282 : use crate::{Null, ValueSer};
283 :
284 : #[test]
285 1 : fn object() {
286 1 : let mut buf = vec![];
287 1 : let mut object = ValueSer::new(&mut buf).object();
288 1 : object.entry("foo", "bar");
289 1 : object.entry("baz", Null);
290 1 : object.finish();
291 :
292 1 : assert_eq!(buf, br#"{"foo":"bar","baz":null}"#);
293 1 : }
294 :
295 : #[test]
296 1 : fn list() {
297 1 : let mut buf = vec![];
298 1 : let mut list = ValueSer::new(&mut buf).list();
299 1 : list.entry().value("bar");
300 1 : list.entry().value(Null);
301 1 : list.finish();
302 :
303 1 : assert_eq!(buf, br#"["bar",null]"#);
304 1 : }
305 :
306 : #[test]
307 1 : fn object_macro() {
308 1 : let res = crate::value_to_string!(|obj| {
309 1 : crate::value_as_object!(|obj| {
310 1 : obj.entry("foo", "bar");
311 1 : obj.entry("baz", Null);
312 1 : })
313 1 : });
314 :
315 1 : assert_eq!(res, r#"{"foo":"bar","baz":null}"#);
316 1 : }
317 :
318 : #[test]
319 1 : fn list_macro() {
320 1 : let res = crate::value_to_string!(|list| {
321 1 : crate::value_as_list!(|list| {
322 1 : list.entry().value("bar");
323 1 : list.entry().value(Null);
324 1 : })
325 1 : });
326 :
327 1 : assert_eq!(res, r#"["bar",null]"#);
328 1 : }
329 :
330 : #[test]
331 1 : fn rollback_on_drop() {
332 1 : let res = crate::value_to_string!(|list| {
333 1 : crate::value_as_list!(|list| {
334 1 : list.entry().value("bar");
335 :
336 : 'cancel: {
337 1 : let nested_list = list.entry();
338 1 : crate::value_as_list!(|nested_list| {
339 1 : nested_list.entry().value(1);
340 :
341 1 : assert_eq!(nested_list.as_buffer(), br#"["bar",[1"#);
342 1 : if true {
343 1 : break 'cancel;
344 0 : }
345 : })
346 : }
347 :
348 1 : assert_eq!(list.as_buffer(), br#"["bar""#);
349 :
350 1 : list.entry().value(Null);
351 : })
352 : });
353 :
354 1 : assert_eq!(res, r#"["bar",null]"#);
355 1 : }
356 :
357 : #[test]
358 1 : fn rollback_object() {
359 1 : let res = crate::value_to_string!(|obj| {
360 1 : crate::value_as_object!(|obj| {
361 1 : let entry = obj.key("1");
362 1 : entry.value(1_i32);
363 1 :
364 1 : let entry = obj.key("2");
365 1 : let entry = {
366 1 : let mut nested_obj = entry.object();
367 1 : nested_obj.entry("foo", "bar");
368 1 : nested_obj.rollback()
369 1 : };
370 1 :
371 1 : entry.value(2_i32);
372 1 : })
373 1 : });
374 :
375 1 : assert_eq!(res, r#"{"1":1,"2":2}"#);
376 1 : }
377 :
378 : #[test]
379 1 : fn rollback_list() {
380 1 : let res = crate::value_to_string!(|list| {
381 1 : crate::value_as_list!(|list| {
382 1 : let entry = list.entry();
383 1 : entry.value(1_i32);
384 1 :
385 1 : let entry = list.entry();
386 1 : let entry = {
387 1 : let mut nested_list = entry.list();
388 1 : nested_list.push("foo");
389 1 : nested_list.rollback()
390 1 : };
391 1 :
392 1 : entry.value(2_i32);
393 1 : })
394 1 : });
395 :
396 1 : assert_eq!(res, r#"[1,2]"#);
397 1 : }
398 :
399 : #[test]
400 1 : fn string_escaping() {
401 1 : let mut buf = vec![];
402 1 : let mut object = ValueSer::new(&mut buf).object();
403 :
404 1 : let key = "hello";
405 1 : let value = "\n world";
406 :
407 1 : object.entry(format_args!("{key:?}"), value);
408 1 : object.finish();
409 :
410 1 : assert_eq!(buf, br#"{"\"hello\"":"\n world"}"#);
411 1 : }
412 : }
|