simd_json/value/tape/
trait_impls.rs

1use std::{
2    borrow::Borrow,
3    hash::Hash,
4    io::{self, Write},
5};
6
7use value_trait::{
8    base::{TypedValue, ValueAsScalar, ValueIntoArray, ValueIntoObject, ValueIntoString, Writable},
9    derived::{
10        ValueObjectAccessAsScalar, ValueObjectAccessTryAsScalar, ValueTryAsScalar,
11        ValueTryIntoString,
12    },
13    generator::{
14        BaseGenerator, DumpGenerator, PrettyGenerator, PrettyWriterGenerator, WriterGenerator,
15    },
16    StaticNode, TryTypeError, ValueType,
17};
18
19use crate::Node;
20
21use super::{Array, Object, Value};
22
23// Custom functions
24impl<'tape, 'input> Value<'tape, 'input> {
25    fn as_static(&self) -> Option<StaticNode> {
26        match self.0.first()? {
27            Node::Static(s) => Some(*s),
28            _ => None,
29        }
30    }
31}
32
33// TypedContainerValue
34impl<'tape, 'input> Value<'tape, 'input> {
35    /// returns true if the current value can be represented as an array
36    #[must_use]
37    pub fn is_array(&self) -> bool {
38        self.as_array().is_some()
39    }
40
41    /// returns true if the current value can be represented as an object
42    #[must_use]
43    pub fn is_object(&self) -> bool {
44        self.as_object().is_some()
45    }
46}
47
48impl<'tape, 'input> ValueAsScalar for Value<'tape, 'input>
49where
50    'input: 'tape,
51{
52    #[cfg_attr(not(feature = "no-inline"), inline)]
53    fn as_null(&self) -> Option<()> {
54        self.as_static()?.as_null()
55    }
56
57    #[cfg_attr(not(feature = "no-inline"), inline)]
58    fn as_bool(&self) -> Option<bool> {
59        self.as_static()?.as_bool()
60    }
61
62    #[cfg_attr(not(feature = "no-inline"), inline)]
63    fn as_i64(&self) -> Option<i64> {
64        self.as_static()?.as_i64()
65    }
66
67    #[cfg_attr(not(feature = "no-inline"), inline)]
68    fn as_u64(&self) -> Option<u64> {
69        self.as_static()?.as_u64()
70    }
71
72    #[cfg_attr(not(feature = "no-inline"), inline)]
73    fn as_f64(&self) -> Option<f64> {
74        self.as_static()?.as_f64()
75    }
76
77    #[cfg_attr(not(feature = "no-inline"), inline)]
78    fn as_str(&self) -> Option<&'input str> {
79        self.into_string()
80    }
81}
82
83impl<'tape, 'input> ValueIntoString for Value<'tape, 'input> {
84    type String = &'input str;
85
86    fn into_string(self) -> Option<&'input str> {
87        if let Some(Node::String(v)) = self.0.first() {
88            Some(v)
89        } else {
90            None
91        }
92    }
93}
94
95impl<'tape, 'input> ValueIntoArray for Value<'tape, 'input> {
96    type Array = Array<'tape, 'input>;
97    #[must_use]
98    fn into_array(self) -> Option<Self::Array> {
99        if let Some(Node::Array { count, .. }) = self.0.first() {
100            // we add one element as we want to keep the array header
101            let count = *count + 1;
102            Some(Array(&self.0[..count]))
103        } else {
104            None
105        }
106    }
107}
108impl<'tape, 'input> ValueIntoObject for Value<'tape, 'input> {
109    type Object = Object<'tape, 'input>;
110    #[must_use]
111    fn into_object(self) -> Option<Self::Object> {
112        if let Some(Node::Object { count, .. }) = self.0.first() {
113            // we add one element as we want to keep the object header
114            let count = *count + 1;
115            Some(Object(&self.0[..count]))
116        } else {
117            None
118        }
119    }
120}
121
122impl<'tape, 'input> TypedValue for Value<'tape, 'input> {
123    #[cfg_attr(not(feature = "no-inline"), inline)]
124    #[must_use]
125    fn value_type(&self) -> ValueType {
126        match self.0.first().expect("invalid tape value") {
127            Node::Static(StaticNode::Null) => ValueType::Null,
128            Node::Static(StaticNode::Bool(_)) => ValueType::Bool,
129            Node::Static(StaticNode::I64(_)) => ValueType::I64,
130            #[cfg(feature = "128bit")]
131            Node::Static(StaticNode::I128(_)) => ValueType::I128,
132            Node::Static(StaticNode::U64(_)) => ValueType::U64,
133            #[cfg(feature = "128bit")]
134            Node::Static(StaticNode::U128(_)) => ValueType::U128,
135            Node::Static(StaticNode::F64(_)) => ValueType::F64,
136            Node::String(_) => ValueType::String,
137            Node::Array { .. } => ValueType::Array,
138            Node::Object { .. } => ValueType::Object,
139        }
140    }
141}
142
143// TryValueObjectAccess
144impl<'tape, 'input> Value<'tape, 'input> {
145    // type Key = &str;
146    // type Target = Value<'tape, 'input>;
147
148    /// Tries to get a value based on a key, returns a `TryTypeError` if the
149    /// current Value isn't an Object, returns `None` if the key isn't in the object
150    /// # Errors
151    /// if the value is not an object
152    pub fn try_get<Q>(&self, k: &Q) -> Result<Option<Value<'tape, 'input>>, TryTypeError>
153    where
154        str: Borrow<Q> + Hash + Eq,
155        Q: ?Sized + Hash + Eq + Ord,
156    {
157        Ok(self.try_as_object()?.get(k))
158    }
159}
160
161//TryValueArrayAccess
162impl<'tape, 'input> Value<'tape, 'input>
163where
164    'input: 'tape,
165{
166    /// Tries to get a value based on n index, returns a type error if the
167    /// current value isn't an Array, returns `None` if the index is out of bounds
168    /// # Errors
169    /// if the requested type doesn't match the actual type or the value is not an object
170    pub fn try_get_idx(&self, i: usize) -> Result<Option<Value<'tape, 'input>>, TryTypeError> {
171        Ok(self.try_as_array()?.get(i))
172    }
173}
174
175//ValueAsContainer
176impl<'tape, 'input> Value<'tape, 'input>
177where
178    'input: 'tape,
179{
180    /// Tries to represent the value as an array and returns a reference to it
181    #[must_use]
182    pub fn as_array(&self) -> Option<Array<'tape, 'input>> {
183        if let Some(Node::Array { count, .. }) = self.0.first() {
184            // we add one element as we want to keep the array header
185            let count = *count + 1;
186            Some(Array(&self.0[..count]))
187        } else {
188            None
189        }
190    }
191
192    /// Tries to represent the value as an array and returns a reference to it
193    #[must_use]
194    pub fn as_object(&self) -> Option<Object<'tape, 'input>> {
195        if let Some(Node::Object { count, .. }) = self.0.first() {
196            // we add one element as we want to keep the object header
197            let count = *count + 1;
198            Some(Object(&self.0[..count]))
199        } else {
200            None
201        }
202    }
203}
204
205// ContainerValueTryAs (needed as we don't have ValueAsContainer)
206impl<'tape, 'input> Value<'tape, 'input> {
207    /// Tries to represent the value as an array and returns a reference to it
208    /// # Errors
209    /// if the requested type doesn't match the actual type
210    pub fn try_as_array(&self) -> Result<Array<'tape, 'input>, TryTypeError> {
211        self.as_array().ok_or(TryTypeError {
212            expected: ValueType::Array,
213            got: self.value_type(),
214        })
215    }
216
217    /// Tries to represent the value as an object and returns a reference to it
218    /// # Errors
219    /// if the requested type doesn't match the actual type
220    pub fn try_as_object(&self) -> Result<Object<'tape, 'input>, TryTypeError> {
221        self.as_object().ok_or(TryTypeError {
222            expected: ValueType::Object,
223            got: self.value_type(),
224        })
225    }
226}
227// ValueObjectAccess (needed as we don't have ValueAsContainer ) and can't return references
228impl<'tape, 'input> Value<'tape, 'input> {
229    /// Gets a ref to a value based on a key, returns `None` if the
230    /// current Value isn't an Object or doesn't contain the key
231    /// it was asked for.
232    #[must_use]
233    pub fn get<Q>(&self, k: &Q) -> Option<Value<'tape, 'input>>
234    where
235        str: Borrow<Q> + Hash + Eq,
236        Q: ?Sized + Hash + Eq + Ord,
237    {
238        self.as_object().and_then(|a| a.get(k))
239    }
240
241    /// Checks if a Value contains a given key. This will return
242    /// flase if Value isn't an object  
243    #[must_use]
244    pub fn contains_key(&self, k: &str) -> bool {
245        self.as_object().and_then(|a| a.get(k)).is_some()
246    }
247}
248
249// ValueArrayAccess (needed as we don't have ValueAsContainer)
250impl<'tape, 'input> Value<'tape, 'input> {
251    /// Gets a ref to a value based on n index, returns `None` if the
252    /// current Value isn't an Array or doesn't contain the index
253    /// it was asked for.
254    #[must_use]
255    pub fn get_idx(&self, i: usize) -> Option<Value<'tape, 'input>> {
256        self.as_array().and_then(|a| a.get(i))
257    }
258}
259
260impl<'tape, 'input> ValueObjectAccessAsScalar for Value<'tape, 'input>
261where
262    'input: 'tape,
263{
264    type Key = str;
265
266    fn get_bool<Q>(&self, k: &Q) -> Option<bool>
267    where
268        str: Borrow<Q> + Hash + Eq,
269        Q: ?Sized + Hash + Eq + Ord,
270    {
271        self.get(k)?.as_bool()
272    }
273
274    #[cfg_attr(not(feature = "no-inline"), inline)]
275    fn get_i128<Q>(&self, k: &Q) -> Option<i128>
276    where
277        str: Borrow<Q> + Hash + Eq,
278        Q: ?Sized + Hash + Eq + Ord,
279    {
280        self.get(k)?.as_i128()
281    }
282
283    #[cfg_attr(not(feature = "no-inline"), inline)]
284    fn get_i64<Q>(&self, k: &Q) -> Option<i64>
285    where
286        str: Borrow<Q> + Hash + Eq,
287        Q: ?Sized + Hash + Eq + Ord,
288    {
289        self.get(k)?.as_i64()
290    }
291
292    #[cfg_attr(not(feature = "no-inline"), inline)]
293    fn get_i32<Q>(&self, k: &Q) -> Option<i32>
294    where
295        str: Borrow<Q> + Hash + Eq,
296        Q: ?Sized + Hash + Eq + Ord,
297    {
298        self.get(k)?.as_i32()
299    }
300
301    #[cfg_attr(not(feature = "no-inline"), inline)]
302    fn get_i16<Q>(&self, k: &Q) -> Option<i16>
303    where
304        str: Borrow<Q> + Hash + Eq,
305        Q: ?Sized + Hash + Eq + Ord,
306    {
307        self.get(k)?.as_i16()
308    }
309
310    #[cfg_attr(not(feature = "no-inline"), inline)]
311    fn get_i8<Q>(&self, k: &Q) -> Option<i8>
312    where
313        str: Borrow<Q> + Hash + Eq,
314        Q: ?Sized + Hash + Eq + Ord,
315    {
316        self.get(k)?.as_i8()
317    }
318
319    #[cfg_attr(not(feature = "no-inline"), inline)]
320    fn get_u128<Q>(&self, k: &Q) -> Option<u128>
321    where
322        str: Borrow<Q> + Hash + Eq,
323        Q: ?Sized + Hash + Eq + Ord,
324    {
325        self.get(k)?.as_u128()
326    }
327
328    #[cfg_attr(not(feature = "no-inline"), inline)]
329    fn get_u64<Q>(&self, k: &Q) -> Option<u64>
330    where
331        str: Borrow<Q> + Hash + Eq,
332        Q: ?Sized + Hash + Eq + Ord,
333    {
334        self.get(k).and_then(|v| v.as_u64())
335    }
336
337    #[cfg_attr(not(feature = "no-inline"), inline)]
338    fn get_usize<Q>(&self, k: &Q) -> Option<usize>
339    where
340        str: Borrow<Q> + Hash + Eq,
341        Q: ?Sized + Hash + Eq + Ord,
342    {
343        self.get(k).and_then(|v| v.as_usize())
344    }
345
346    #[cfg_attr(not(feature = "no-inline"), inline)]
347    fn get_u32<Q>(&self, k: &Q) -> Option<u32>
348    where
349        str: Borrow<Q> + Hash + Eq,
350        Q: ?Sized + Hash + Eq + Ord,
351    {
352        self.get(k).and_then(|v| v.as_u32())
353    }
354
355    #[cfg_attr(not(feature = "no-inline"), inline)]
356    fn get_u16<Q>(&self, k: &Q) -> Option<u16>
357    where
358        str: Borrow<Q> + Hash + Eq,
359        Q: ?Sized + Hash + Eq + Ord,
360    {
361        self.get(k).and_then(|v| v.as_u16())
362    }
363
364    #[cfg_attr(not(feature = "no-inline"), inline)]
365    fn get_u8<Q>(&self, k: &Q) -> Option<u8>
366    where
367        str: Borrow<Q> + Hash + Eq,
368        Q: ?Sized + Hash + Eq + Ord,
369    {
370        self.get(k).and_then(|v| v.as_u8())
371    }
372
373    #[cfg_attr(not(feature = "no-inline"), inline)]
374    fn get_f64<Q>(&self, k: &Q) -> Option<f64>
375    where
376        str: Borrow<Q> + Hash + Eq,
377        Q: ?Sized + Hash + Eq + Ord,
378    {
379        self.get(k).and_then(|v| v.as_f64())
380    }
381
382    #[cfg_attr(not(feature = "no-inline"), inline)]
383    fn get_f32<Q>(&self, k: &Q) -> Option<f32>
384    where
385        str: Borrow<Q> + Hash + Eq,
386        Q: ?Sized + Hash + Eq + Ord,
387    {
388        self.get(k).and_then(|v| v.as_f32())
389    }
390
391    #[cfg_attr(not(feature = "no-inline"), inline)]
392    fn get_str<Q>(&self, k: &Q) -> Option<&'input str>
393    where
394        str: Borrow<Q> + Hash + Eq,
395        Q: ?Sized + Hash + Eq + Ord,
396    {
397        if let Some(Node::String(v)) = self.get(k)?.0.first() {
398            Some(v)
399        } else {
400            None
401        }
402    }
403}
404
405// ValueObjectContainerAccess
406impl<'tape, 'input> Value<'tape, 'input> {
407    /// Tries to get an element of an object as a array
408    #[must_use]
409    pub fn get_array<Q>(&self, k: &Q) -> Option<Array<'tape, 'input>>
410    where
411        str: Borrow<Q> + Hash + Eq,
412        Q: ?Sized + Hash + Eq + Ord,
413    {
414        let mut len = self.0[0].object_len().ok()?;
415        let mut idx = 1;
416        while len > 0 {
417            let Some(s) = self.0[idx].as_str() else {
418                unreachable!()
419            };
420            idx += 1;
421            len -= 1;
422            let count = self.0[idx].count();
423            let s: &Q = s.borrow();
424            if s == k {
425                let count: usize = self.0[idx].array_count().ok()?;
426                return Some(Array(&self.0[idx..idx + count]));
427            }
428            idx += count;
429        }
430        None
431    }
432
433    /// Tries to get an element of an object as a object
434    #[must_use]
435    pub fn get_object<Q>(&self, k: &Q) -> Option<Object<'tape, 'input>>
436    where
437        str: Borrow<Q> + Hash + Eq,
438        Q: ?Sized + Hash + Eq + Ord,
439    {
440        let mut len = self.0[0].object_len().ok()?;
441        let mut idx = 1;
442        while len > 0 {
443            let Some(s) = self.0[idx].as_str() else {
444                unreachable!()
445            };
446            idx += 1;
447            len -= 1;
448            let count = self.0[idx].count();
449            let s: &Q = s.borrow();
450            if s == k {
451                let count: usize = self.0[idx].object_count().ok()?;
452                return Some(Object(&self.0[idx..idx + count]));
453            }
454            idx += count;
455        }
456        None
457    }
458}
459// TryValueObjectContainerAccess
460impl<'tape, 'input> Value<'tape, 'input> {
461    /// Tries to get an element of an object as an array, returns
462    /// an error if it isn't a array
463    /// # Errors
464    /// if the requested type doesn't match the actual type or the value is not an object
465    pub fn try_get_array<Q>(&self, k: &Q) -> Result<Option<Array<'tape, 'input>>, TryTypeError>
466    where
467        str: Borrow<Q> + Hash + Eq,
468        Q: ?Sized + Hash + Eq + Ord,
469    {
470        let mut len = self.0[0].object_len()?;
471        let mut idx = 1;
472        while len > 0 {
473            let Some(s) = self.0[idx].as_str() else {
474                unreachable!()
475            };
476            idx += 1;
477            len -= 1;
478            let count = self.0[idx].count();
479            let s: &Q = s.borrow();
480            if s == k {
481                let count: usize = self.0[idx].array_count()?;
482                return Ok(Some(Array(&self.0[idx..idx + count])));
483            }
484            idx += count;
485        }
486        Ok(None)
487    }
488
489    /// Tries to get an element of an object as an object, returns
490    /// an error if it isn't an object
491    ///
492    /// # Errors
493    /// if the requested type doesn't match the actual type or the value is not an object
494    pub fn try_get_object<Q>(&self, k: &Q) -> Result<Option<Object<'tape, 'input>>, TryTypeError>
495    where
496        str: Borrow<Q> + Hash + Eq,
497        Q: ?Sized + Hash + Eq + Ord,
498    {
499        let mut len = self.0[0].object_len()?;
500        let mut idx = 1;
501        while len > 0 {
502            let Some(s) = self.0[idx].as_str() else {
503                unreachable!()
504            };
505            idx += 1;
506            len -= 1;
507            let count = self.0[idx].count();
508            let s: &Q = s.borrow();
509            if s == k {
510                let count: usize = self.0[idx].object_count()?;
511                return Ok(Some(Object(&self.0[idx..idx + count])));
512            }
513            idx += count;
514        }
515        Ok(None)
516    }
517}
518
519impl<'tape, 'input> ValueObjectAccessTryAsScalar for Value<'tape, 'input> {
520    type Key = str;
521    fn try_get_bool<Q>(&self, k: &Q) -> Result<Option<bool>, TryTypeError>
522    where
523        str: Borrow<Q> + Hash + Eq,
524        Q: ?Sized + Hash + Eq + Ord,
525    {
526        self.try_get(k)?.map(|v| v.try_as_bool()).transpose()
527    }
528
529    #[cfg_attr(not(feature = "no-inline"), inline)]
530    fn try_get_i128<Q>(&self, k: &Q) -> Result<Option<i128>, TryTypeError>
531    where
532        str: Borrow<Q> + Hash + Eq,
533        Q: ?Sized + Hash + Eq + Ord,
534    {
535        self.try_get(k)?.map(|v| v.try_as_i128()).transpose()
536    }
537
538    #[cfg_attr(not(feature = "no-inline"), inline)]
539    fn try_get_i64<Q>(&self, k: &Q) -> Result<Option<i64>, TryTypeError>
540    where
541        str: Borrow<Q> + Hash + Eq,
542        Q: ?Sized + Hash + Eq + Ord,
543    {
544        self.try_get(k)?.map(|v| v.try_as_i64()).transpose()
545    }
546
547    #[cfg_attr(not(feature = "no-inline"), inline)]
548    fn try_get_i32<Q>(&self, k: &Q) -> Result<Option<i32>, TryTypeError>
549    where
550        str: Borrow<Q> + Hash + Eq,
551        Q: ?Sized + Hash + Eq + Ord,
552    {
553        self.try_get(k)?.map(|v| v.try_as_i32()).transpose()
554    }
555
556    #[cfg_attr(not(feature = "no-inline"), inline)]
557    fn try_get_i16<Q>(&self, k: &Q) -> Result<Option<i16>, TryTypeError>
558    where
559        str: Borrow<Q> + Hash + Eq,
560        Q: ?Sized + Hash + Eq + Ord,
561    {
562        self.try_get(k)?.map(|v| v.try_as_i16()).transpose()
563    }
564
565    #[cfg_attr(not(feature = "no-inline"), inline)]
566    fn try_get_i8<Q>(&self, k: &Q) -> Result<Option<i8>, TryTypeError>
567    where
568        str: Borrow<Q> + Hash + Eq,
569        Q: ?Sized + Hash + Eq + Ord,
570    {
571        self.try_get(k)?.map(|v| v.try_as_i8()).transpose()
572    }
573
574    #[cfg_attr(not(feature = "no-inline"), inline)]
575    fn try_get_u128<Q>(&self, k: &Q) -> Result<Option<u128>, TryTypeError>
576    where
577        str: Borrow<Q> + Hash + Eq,
578        Q: ?Sized + Hash + Eq + Ord,
579    {
580        self.try_get(k)?.map(|v| v.try_as_u128()).transpose()
581    }
582
583    #[cfg_attr(not(feature = "no-inline"), inline)]
584    fn try_get_u64<Q>(&self, k: &Q) -> Result<Option<u64>, TryTypeError>
585    where
586        str: Borrow<Q> + Hash + Eq,
587        Q: ?Sized + Hash + Eq + Ord,
588    {
589        self.try_get(k)?.map(|v| v.try_as_u64()).transpose()
590    }
591
592    #[cfg_attr(not(feature = "no-inline"), inline)]
593    fn try_get_usize<Q>(&self, k: &Q) -> Result<Option<usize>, TryTypeError>
594    where
595        str: Borrow<Q> + Hash + Eq,
596        Q: ?Sized + Hash + Eq + Ord,
597    {
598        self.try_get(k)?.map(|v| v.try_as_usize()).transpose()
599    }
600
601    #[cfg_attr(not(feature = "no-inline"), inline)]
602    fn try_get_u32<Q>(&self, k: &Q) -> Result<Option<u32>, TryTypeError>
603    where
604        str: Borrow<Q> + Hash + Eq,
605        Q: ?Sized + Hash + Eq + Ord,
606    {
607        self.try_get(k)?.map(|v| v.try_as_u32()).transpose()
608    }
609
610    #[cfg_attr(not(feature = "no-inline"), inline)]
611    fn try_get_u16<Q>(&self, k: &Q) -> Result<Option<u16>, TryTypeError>
612    where
613        str: Borrow<Q> + Hash + Eq,
614        Q: ?Sized + Hash + Eq + Ord,
615    {
616        self.try_get(k)?.map(|v| v.try_as_u16()).transpose()
617    }
618
619    #[cfg_attr(not(feature = "no-inline"), inline)]
620    fn try_get_u8<Q>(&self, k: &Q) -> Result<Option<u8>, TryTypeError>
621    where
622        str: Borrow<Q> + Hash + Eq,
623        Q: ?Sized + Hash + Eq + Ord,
624    {
625        self.try_get(k)?.map(|v| v.try_as_u8()).transpose()
626    }
627
628    #[cfg_attr(not(feature = "no-inline"), inline)]
629    fn try_get_f64<Q>(&self, k: &Q) -> Result<Option<f64>, TryTypeError>
630    where
631        str: Borrow<Q> + Hash + Eq,
632        Q: ?Sized + Hash + Eq + Ord,
633    {
634        self.try_get(k)?.map(|v| v.try_as_f64()).transpose()
635    }
636
637    #[cfg_attr(not(feature = "no-inline"), inline)]
638    fn try_get_f32<Q>(&self, k: &Q) -> Result<Option<f32>, TryTypeError>
639    where
640        str: Borrow<Q> + Hash + Eq,
641        Q: ?Sized + Hash + Eq + Ord,
642    {
643        self.try_get(k)?.map(|v| v.try_as_f32()).transpose()
644    }
645
646    #[cfg_attr(not(feature = "no-inline"), inline)]
647    fn try_get_str<Q>(&self, k: &Q) -> Result<Option<&str>, TryTypeError>
648    where
649        str: Borrow<Q> + Hash + Eq,
650        Q: ?Sized + Hash + Eq + Ord,
651    {
652        self.try_as_object()?
653            .get(k)
654            .map(ValueTryIntoString::try_into_string)
655            .transpose()
656    }
657}
658
659impl<'tape, 'input> Writable for Value<'tape, 'input> {
660    #[cfg_attr(not(feature = "no-inline"), inline)]
661    fn encode(&self) -> String {
662        let mut g = DumpGenerator::new();
663        let _r = g.write_json(self);
664        g.consume()
665    }
666
667    #[cfg_attr(not(feature = "no-inline"), inline)]
668    fn encode_pp(&self) -> String {
669        let mut g = PrettyGenerator::new(2);
670        let _r = g.write_json(self);
671        g.consume()
672    }
673
674    #[cfg_attr(not(feature = "no-inline"), inline)]
675    fn write<'writer, W>(&self, w: &mut W) -> io::Result<()>
676    where
677        W: 'writer + Write,
678    {
679        let mut g = WriterGenerator::new(w);
680        g.write_json(self)
681    }
682
683    #[cfg_attr(not(feature = "no-inline"), inline)]
684    fn write_pp<'writer, W>(&self, w: &mut W) -> io::Result<()>
685    where
686        W: 'writer + Write,
687    {
688        let mut g = PrettyWriterGenerator::new(w, 2);
689        g.write_json(self)
690    }
691}
692
693trait Generator: BaseGenerator {
694    type T: Write;
695
696    #[cfg_attr(not(feature = "no-inline"), inline)]
697    fn write_object(&mut self, object: &Object) -> io::Result<()> {
698        if object.is_empty() {
699            self.write(b"{}")
700        } else {
701            let mut iter = object.iter();
702            stry!(self.write(b"{"));
703
704            // We know this exists since it's not empty
705            let (key, value) = if let Some(v) = iter.next() {
706                v
707            } else {
708                // We check against size
709                unreachable!();
710            };
711            self.indent();
712            stry!(self.new_line());
713            stry!(self.write_simple_string(key));
714            stry!(self.write_min(b": ", b':'));
715            stry!(self.write_json(&value));
716
717            for (key, value) in iter {
718                stry!(self.write(b","));
719                stry!(self.new_line());
720                stry!(self.write_simple_string(key));
721                stry!(self.write_min(b": ", b':'));
722                stry!(self.write_json(&value));
723            }
724            self.dedent();
725            stry!(self.new_line());
726            self.write(b"}")
727        }
728    }
729
730    #[cfg_attr(not(feature = "no-inline"), inline)]
731    fn write_json(&mut self, json: &Value) -> io::Result<()> {
732        //FIXME no expect
733        match *json.0.first().expect("invalid JSON") {
734            Node::Static(StaticNode::Null) => self.write(b"null"),
735            Node::Static(StaticNode::I64(number)) => self.write_int(number),
736            #[cfg(feature = "128bit")]
737            Node::Static(StaticNode::I128(number)) => self.write_int(number),
738            Node::Static(StaticNode::U64(number)) => self.write_int(number),
739            #[cfg(feature = "128bit")]
740            Node::Static(StaticNode::U128(number)) => self.write_int(number),
741            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
742            Node::Static(StaticNode::F64(number)) => self.write_float(number.into()),
743            Node::Static(StaticNode::Bool(true)) => self.write(b"true"),
744            Node::Static(StaticNode::Bool(false)) => self.write(b"false"),
745            Node::String(string) => self.write_string(string),
746            Node::Array { count, .. } => {
747                if count == 0 {
748                    self.write(b"[]")
749                } else {
750                    let array = Array(&json.0[..=count]);
751                    let mut iter = array.iter();
752                    // We know we have one item
753
754                    let item = if let Some(v) = iter.next() {
755                        v
756                    } else {
757                        // We check against size
758                        unreachable!();
759                    };
760                    stry!(self.write(b"["));
761                    self.indent();
762
763                    stry!(self.new_line());
764                    stry!(self.write_json(&item));
765
766                    for item in iter {
767                        stry!(self.write(b","));
768                        stry!(self.new_line());
769                        stry!(self.write_json(&item));
770                    }
771                    self.dedent();
772                    stry!(self.new_line());
773                    self.write(b"]")
774                }
775            }
776            Node::Object { count, .. } => self.write_object(&Object(&json.0[..=count])),
777        }
778    }
779}
780
781trait FastGenerator: BaseGenerator {
782    type T: Write;
783
784    #[cfg_attr(not(feature = "no-inline"), inline)]
785    fn write_object(&mut self, object: &Object) -> io::Result<()> {
786        if object.is_empty() {
787            self.write(b"{}")
788        } else {
789            let mut iter = object.iter();
790            stry!(self.write(b"{\""));
791
792            // We know this exists since it's not empty
793            let (key, value) = if let Some(v) = iter.next() {
794                v
795            } else {
796                // We check against size
797                unreachable!();
798            };
799            stry!(self.write_simple_str_content(key));
800            stry!(self.write(b"\":"));
801            stry!(self.write_json(&value));
802
803            for (key, value) in iter {
804                stry!(self.write(b",\""));
805                stry!(self.write_simple_str_content(key));
806                stry!(self.write(b"\":"));
807                stry!(self.write_json(&value));
808            }
809            self.write(b"}")
810        }
811    }
812
813    #[cfg_attr(not(feature = "no-inline"), inline)]
814    fn write_json(&mut self, json: &Value) -> io::Result<()> {
815        match *json.0.first().expect("invalid JSON") {
816            Node::Static(StaticNode::Null) => self.write(b"null"),
817            Node::Static(StaticNode::I64(number)) => self.write_int(number),
818            #[cfg(feature = "128bit")]
819            Node::Static(StaticNode::I128(number)) => self.write_int(number),
820            Node::Static(StaticNode::U64(number)) => self.write_int(number),
821            #[cfg(feature = "128bit")]
822            Node::Static(StaticNode::U128(number)) => self.write_int(number),
823            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
824            Node::Static(StaticNode::F64(number)) => self.write_float(number.into()),
825            Node::Static(StaticNode::Bool(true)) => self.write(b"true"),
826            Node::Static(StaticNode::Bool(false)) => self.write(b"false"),
827            Node::String(string) => self.write_string(string),
828            Node::Array { count, .. } => {
829                if count == 0 {
830                    self.write(b"[]")
831                } else {
832                    let array = Array(&json.0[..=count]);
833                    let mut iter = array.iter();
834                    // We know we have one item
835                    let item = if let Some(v) = iter.next() {
836                        v
837                    } else {
838                        // We check against size
839                        unreachable!();
840                    };
841
842                    stry!(self.write(b"["));
843                    stry!(self.write_json(&item));
844
845                    for item in iter {
846                        stry!(self.write(b","));
847                        stry!(self.write_json(&item));
848                    }
849                    self.write(b"]")
850                }
851            }
852            Node::Object { count, .. } => self.write_object(&Object(&json.0[..=count])),
853        }
854    }
855}
856
857impl FastGenerator for DumpGenerator {
858    type T = Vec<u8>;
859}
860
861impl Generator for PrettyGenerator {
862    type T = Vec<u8>;
863}
864
865impl<'writer, W> FastGenerator for WriterGenerator<'writer, W>
866where
867    W: Write,
868{
869    type T = W;
870}
871
872impl<'writer, W> Generator for PrettyWriterGenerator<'writer, W>
873where
874    W: Write,
875{
876    type T = W;
877}