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