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
23impl 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
33impl Value<'_, '_> {
35 #[must_use]
37 pub fn is_array(&self) -> bool {
38 self.as_array().is_some()
39 }
40
41 #[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 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 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
140impl<'tape, 'input> Value<'tape, 'input> {
142 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
158impl<'tape, 'input> Value<'tape, 'input>
160where
161 'input: 'tape,
162{
163 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
172impl<'tape, 'input> Value<'tape, 'input>
174where
175 'input: 'tape,
176{
177 #[must_use]
179 pub fn as_array(&self) -> Option<Array<'tape, 'input>> {
180 if let Some(Node::Array { count, .. }) = self.0.first() {
181 let count = *count + 1;
183 Some(Array(&self.0[..count]))
184 } else {
185 None
186 }
187 }
188
189 #[must_use]
191 pub fn as_object(&self) -> Option<Object<'tape, 'input>> {
192 if let Some(Node::Object { count, .. }) = self.0.first() {
193 let count = *count + 1;
195 Some(Object(&self.0[..count]))
196 } else {
197 None
198 }
199 }
200}
201
202impl<'tape, 'input> Value<'tape, 'input> {
204 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 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}
224impl<'tape, 'input> Value<'tape, 'input> {
226 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 #[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
245impl<'tape, 'input> Value<'tape, 'input> {
247 #[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
401impl<'tape, 'input> Value<'tape, 'input> {
403 #[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 #[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}
461impl<'tape, 'input> Value<'tape, 'input> {
463 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 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 let Some((key, value)) = iter.next() else {
714 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 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)] 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 let Some(item) = iter.next() else {
761 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 let Some((key, value)) = iter.next() else {
798 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)] 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 let Some(item) = iter.next() else {
838 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}