nyoom_json/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3
4use core::mem::ManuallyDrop;
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8#[cfg(feature = "alloc")]
9use alloc::string::String;
10
11use sealed::sealed;
12
13mod escape;
14mod write_to_json;
15pub use write_to_json::*;
16
17#[inline]
18#[cold]
19fn cold() {}
20
21/// Any buffer which JSON may be written into.
22pub trait JsonBuffer {
23 fn push(&mut self, c: char);
24 fn push_str(&mut self, s: &str);
25 fn reserve(&mut self, l: usize);
26}
27
28impl<S> JsonBuffer for &mut S
29where
30 S: JsonBuffer,
31{
32 #[inline(always)]
33 fn push(&mut self, c: char) {
34 (*self).push(c)
35 }
36
37 #[inline(always)]
38 fn push_str(&mut self, s: &str) {
39 (*self).push_str(s)
40 }
41
42 #[inline(always)]
43 fn reserve(&mut self, l: usize) {
44 (*self).reserve(l)
45 }
46}
47
48#[cfg(feature = "alloc")]
49impl JsonBuffer for String {
50 #[inline(always)]
51 fn push(&mut self, c: char) {
52 self.push(c)
53 }
54
55 #[inline(always)]
56 fn push_str(&mut self, s: &str) {
57 self.push_str(s)
58 }
59
60 #[inline(always)]
61 fn reserve(&mut self, l: usize) {
62 self.reserve(l)
63 }
64}
65
66/// A general JSON serializer, over a mutable buffer of some sort.
67/// # Examples
68/// ```
69/// use nyoom_json::Serializer;
70///
71/// let mut out = String::new();
72/// let mut ser = Serializer::new(&mut out);
73///
74/// let mut obj = ser.object();
75/// obj.field("kind", "cat");
76/// obj.field("has_been_fed", false);
77/// obj.field("meow_decibels", 45);
78/// obj.end();
79///
80/// let mut arr = ser.array();
81/// arr.add("friends");
82/// arr.add("romans");
83/// arr.add("countrymen");
84/// arr.end();
85///
86/// ser.end();
87/// ```
88#[repr(transparent)]
89pub struct Serializer<'a, S: JsonBuffer> {
90 buf: &'a mut S,
91}
92
93impl<'a, S: JsonBuffer> Serializer<'a, S> {
94 /// Creates a new serializer over a JSON output buffer.
95 pub fn new(buf: &mut S) -> Serializer<S> {
96 Serializer { buf }
97 }
98
99 /// Writes out a single primitive JSON value.
100 /// # Examples
101 ///
102 /// ```
103 /// use nyoom_json::Serializer;
104 ///
105 /// let mut out = String::new();
106 /// let mut ser = Serializer::new(&mut out);
107 /// ser.write(3);
108 /// ```
109 pub fn write(&mut self, val: impl WriteToJson<S>) {
110 val.write_to_json(self.buf)
111 }
112
113 /// Starts serialization of an array.
114 /// # Examples
115 ///
116 /// ```
117 /// use nyoom_json::Serializer;
118 ///
119 /// let mut out = String::new();
120 /// let mut ser = Serializer::new(&mut out);
121 ///
122 /// let mut arr = ser.array();
123 /// arr.add("friends");
124 /// arr.add("romans");
125 /// arr.add("countrymen");
126 /// arr.end();
127 /// ```
128 pub fn array(&mut self) -> ArrayWriter<S> {
129 ArrayWriter::start(self.buf)
130 }
131
132 /// Starts serialization of an object.
133 /// # Examples
134 ///
135 /// ```
136 /// use nyoom_json::Serializer;
137 ///
138 /// let mut out = String::new();
139 /// let mut ser = Serializer::new(&mut out);
140 ///
141 /// let mut obj = ser.object();
142 /// obj.field("kind", "cat");
143 /// obj.field("has_been_fed", false);
144 /// obj.field("meow_decibels", 45);
145 /// obj.end();
146 /// ```
147 pub fn object(&mut self) -> ObjectWriter<S> {
148 ObjectWriter::start(self.buf)
149 }
150
151 /// Ends the serializer.
152 pub fn end(self) {}
153}
154
155/// A serializer that is only able to serialize a single value. See documentation of [Serializer](Serializer)
156pub struct SingleValueSerializer<'a, S: JsonBuffer> {
157 guard: ManuallyDrop<&'a mut S>,
158}
159
160impl<'a, S: JsonBuffer> SingleValueSerializer<'a, S> {
161 pub fn new(val: &'a mut S) -> SingleValueSerializer<'a, S> {
162 SingleValueSerializer {
163 guard: ManuallyDrop::new(val),
164 }
165 }
166
167 pub fn write(mut self, val: impl WriteToJson<S>) {
168 let buf = unsafe { ManuallyDrop::<&'a mut S>::take(&mut self.guard) };
169 val.write_to_json(buf);
170 core::mem::forget(self);
171 }
172
173 pub fn array(mut self) -> ArrayWriter<'a, S> {
174 let buf = unsafe { ManuallyDrop::<&'a mut S>::take(&mut self.guard) };
175 let w = ArrayWriter::start(buf);
176 core::mem::forget(self);
177 w
178 }
179
180 pub fn object(mut self) -> ObjectWriter<'a, S> {
181 let buf = unsafe { ManuallyDrop::<&'a mut S>::take(&mut self.guard) };
182 let w = ObjectWriter::start(buf);
183 core::mem::forget(self);
184 w
185 }
186}
187
188impl<'a, S: JsonBuffer> Drop for SingleValueSerializer<'a, S> {
189 fn drop(&mut self) {
190 unsafe { ManuallyDrop::<&'a mut S>::take(&mut self.guard).push_str("null") };
191 }
192}
193
194/// Serializer for a JSON array.
195pub struct ArrayWriter<'a, S: JsonBuffer> {
196 buf: &'a mut S,
197 first_element: bool,
198}
199
200impl<'a, S: JsonBuffer> ArrayWriter<'a, S> {
201 fn start(buf: &'a mut S) -> ArrayWriter<'a, S> {
202 buf.push('[');
203 ArrayWriter {
204 buf,
205 first_element: true,
206 }
207 }
208
209 fn comma(&mut self) {
210 match self.first_element {
211 true => {
212 cold();
213 self.first_element = false
214 }
215 false => self.buf.push(','),
216 }
217 }
218
219 /// Adds a single primitive JSON value to this array.
220 /// # Examples
221 ///
222 /// ```
223 /// # use nyoom_json::Serializer;
224 /// #
225 /// # let mut out = String::new();
226 /// # let mut ser = Serializer::new(&mut out);
227 /// #
228 /// let mut arr = ser.array();
229 /// arr.add("friends");
230 /// arr.add("romans");
231 /// arr.add("countrymen");
232 /// arr.end();
233 /// ```
234 pub fn add(&mut self, val: impl WriteToJson<S>) {
235 self.comma();
236 val.write_to_json(self.buf)
237 }
238
239 /// Adds a slice of a JSON primitive to this array.
240 /// # Examples
241 ///
242 /// ```
243 /// # use nyoom_json::Serializer;
244 /// #
245 /// # let mut out = String::new();
246 /// # let mut ser = Serializer::new(&mut out);
247 /// #
248 /// let mut arr = ser.array();
249 /// arr.extend(&["friends", "romans", "countrymen"]);
250 /// arr.end();
251 /// ```
252 pub fn extend<V: WriteToJson<S>>(&mut self, vals: impl IntoIterator<Item = V>) {
253 for val in vals {
254 self.add(val);
255 }
256 }
257
258 /// Adds an arbitrary JSON object to this array.
259 ///
260 /// # Arguments
261 ///
262 /// * `encoder` - A closure that encodes a single value into the array.
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// # use nyoom_json::Serializer;
268 /// #
269 /// # let mut out = String::new();
270 /// # let mut ser = Serializer::new(&mut out);
271 /// #
272 /// let mut arr = ser.array();
273 /// arr.add_complex(|mut ser| {
274 /// let mut obj = ser.object();
275 /// obj.field("kitten", true);
276 /// obj.field("cuteness", 10.0);
277 /// });
278 /// arr.end();
279 /// ```
280 pub fn add_complex<F, O>(&mut self, encoder: F) -> O
281 where
282 F: FnOnce(SingleValueSerializer<&mut S>) -> O,
283 {
284 self.comma();
285 encoder(SingleValueSerializer::new(&mut self.buf))
286 }
287
288 /// Adds a JSON object to this array.
289 ///
290 /// # Examples
291 ///
292 /// ```
293 /// # use nyoom_json::Serializer;
294 /// #
295 /// # let mut out = String::new();
296 /// # let mut ser = Serializer::new(&mut out);
297 /// #
298 /// let mut arr = ser.array();
299 ///
300 /// let mut obj = arr.add_object();
301 /// obj.field("kitten", true);
302 /// obj.field("cuteness", 10.0);
303 /// obj.end();
304 ///
305 /// arr.end();
306 /// ```
307 pub fn add_object(&mut self) -> ObjectWriter<S> {
308 self.comma();
309 ObjectWriter::start(self.buf)
310 }
311
312 /// Adds a JSON array.. to this array.
313 ///
314 /// # Examples
315 ///
316 /// ```
317 /// # use nyoom_json::Serializer;
318 /// #
319 /// # let mut out = String::new();
320 /// # let mut ser = Serializer::new(&mut out);
321 /// #
322 /// let mut arr = ser.array();
323 ///
324 /// let mut inner_arr = arr.add_array();
325 /// inner_arr.extend(&[1,2,3]);
326 /// inner_arr.end();
327 ///
328 /// arr.end();
329 /// ```
330 pub fn add_array(&mut self) -> ArrayWriter<S> {
331 self.comma();
332 ArrayWriter::start(self.buf)
333 }
334
335 /// Finishes out the array. Equivalent to drop(arr);
336 pub fn end(self) {}
337}
338
339impl<S: JsonBuffer> Drop for ArrayWriter<'_, S> {
340 fn drop(&mut self) {
341 self.buf.push(']');
342 }
343}
344
345/// A key for a JSON object's field.
346#[sealed]
347pub trait Key {
348 fn write<S: JsonBuffer>(self, out: &mut S);
349}
350
351#[sealed]
352impl Key for UnescapedStr<'_> {
353 fn write<S: JsonBuffer>(self, out: &mut S) {
354 self.write_to_json(out)
355 }
356}
357
358#[sealed]
359impl<T: AsRef<str>> Key for T {
360 fn write<S: JsonBuffer>(self, out: &mut S) {
361 self.as_ref().write_to_json(out)
362 }
363}
364
365/// A serializer for a JSON object.
366pub struct ObjectWriter<'a, S: JsonBuffer> {
367 buf: &'a mut S,
368 first_element: bool,
369}
370
371impl<'a, S: JsonBuffer> ObjectWriter<'a, S> {
372 fn start(buf: &'a mut S) -> ObjectWriter<S> {
373 buf.push('{');
374 ObjectWriter {
375 buf,
376 first_element: true,
377 }
378 }
379
380 fn comma(&mut self) {
381 match self.first_element {
382 true => {
383 cold();
384 self.first_element = false
385 }
386 false => self.buf.push(','),
387 }
388 }
389
390 fn key<K: Key>(&mut self, key: K) {
391 self.comma();
392 key.write(&mut self.buf);
393 self.buf.push(':');
394 }
395
396 /// Adds a field to this object.
397 ///
398 /// # Examples
399 /// ```
400 /// # use nyoom_json::Serializer;
401 /// #
402 /// # let mut out = String::new();
403 /// # let mut ser = Serializer::new(&mut out);
404 /// #
405 /// let mut obj = ser.object();
406 /// obj.field("kind", "cat");
407 /// obj.field("has_been_fed", false);
408 /// obj.field("meow_decibels", 45);
409 /// obj.end();
410 /// ```
411 pub fn field<K: Key>(&mut self, key: K, val: impl WriteToJson<S>) {
412 self.key(key);
413 val.write_to_json(self.buf);
414 }
415
416 /// Adds an arbitrary JSON object to this object.
417 ///
418 /// # Arguments
419 ///
420 /// * `key` - the key for the field
421 /// * `encoder` - A closure that encodes a single value into the field. It may return an arbitrary value that will be passed back to the caller.
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// # use nyoom_json::Serializer;
427 /// #
428 /// # let mut out = String::new();
429 /// # let mut ser = Serializer::new(&mut out);
430 /// #
431 /// let mut obj = ser.object();
432 /// obj.complex_field("numbers", |mut ser| {
433 /// let mut arr = ser.array();
434 /// arr.add(1);
435 /// arr.add(2);
436 /// arr.add("three");
437 /// });
438 /// obj.end()
439 /// ```
440 pub fn complex_field<K, F, O>(&mut self, key: K, encode: F) -> O
441 where
442 K: Key,
443 F: FnOnce(SingleValueSerializer<&mut S>) -> O,
444 {
445 self.key(key);
446 encode(SingleValueSerializer::new(&mut self.buf))
447 }
448
449 /// Adds a JSON object field to this object.
450 ///
451 /// # Examples
452 ///
453 /// ```
454 /// # use nyoom_json::Serializer;
455 /// #
456 /// # let mut out = String::new();
457 /// # let mut ser = Serializer::new(&mut out);
458 /// #
459 /// let mut obj = ser.object();
460 /// obj.field("kitten", true);
461 /// obj.field("cuteness", 10.0);
462 ///
463 /// let mut bed = obj.object_field("bed");
464 /// bed.field("cozy", true);
465 /// bed.field("wear_and_tear", 2.0);
466 /// bed.end();
467 ///
468 /// obj.end();
469 /// ```
470 pub fn object_field<K: Key>(&mut self, key: K) -> ObjectWriter<S> {
471 self.key(key);
472 ObjectWriter::start(self.buf)
473 }
474
475 /// Adds a JSON array field to this object.
476 ///
477 /// # Examples
478 ///
479 /// ```
480 /// # use nyoom_json::Serializer;
481 /// #
482 /// # let mut out = String::new();
483 /// # let mut ser = Serializer::new(&mut out);
484 /// #
485 /// let mut arr = ser.array();
486 ///
487 /// let mut obj = arr.add_object();
488 /// obj.field("kitten", true);
489 /// obj.field("cuteness", 10.0);
490 ///
491 /// let mut toys = obj.array_field("toys");
492 /// toys.extend(&["mouse", "ball", "string", "box", "scratcher"]);
493 /// toys.end();
494 ///
495 /// obj.end();
496 ///
497 /// arr.end();
498 /// ```
499 pub fn array_field<K: Key>(&mut self, key: K) -> ArrayWriter<S> {
500 self.key(key);
501 ArrayWriter::start(self.buf)
502 }
503
504 pub fn end(self) {}
505}
506
507impl<S: JsonBuffer> Drop for ObjectWriter<'_, S> {
508 fn drop(&mut self) {
509 self.buf.push('}');
510 }
511}