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
23impl<'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
33impl<'tape, 'input> Value<'tape, 'input> {
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<'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 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 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
143impl<'tape, 'input> Value<'tape, 'input> {
145 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
161impl<'tape, 'input> Value<'tape, 'input>
163where
164 'input: 'tape,
165{
166 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
175impl<'tape, 'input> Value<'tape, 'input>
177where
178 'input: 'tape,
179{
180 #[must_use]
182 pub fn as_array(&self) -> Option<Array<'tape, 'input>> {
183 if let Some(Node::Array { count, .. }) = self.0.first() {
184 let count = *count + 1;
186 Some(Array(&self.0[..count]))
187 } else {
188 None
189 }
190 }
191
192 #[must_use]
194 pub fn as_object(&self) -> Option<Object<'tape, 'input>> {
195 if let Some(Node::Object { count, .. }) = self.0.first() {
196 let count = *count + 1;
198 Some(Object(&self.0[..count]))
199 } else {
200 None
201 }
202 }
203}
204
205impl<'tape, 'input> Value<'tape, 'input> {
207 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 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}
227impl<'tape, 'input> Value<'tape, 'input> {
229 #[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 #[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
249impl<'tape, 'input> Value<'tape, 'input> {
251 #[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
405impl<'tape, 'input> Value<'tape, 'input> {
407 #[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 #[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}
459impl<'tape, 'input> Value<'tape, 'input> {
461 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 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 let (key, value) = if let Some(v) = iter.next() {
706 v
707 } else {
708 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 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)] 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 let item = if let Some(v) = iter.next() {
755 v
756 } else {
757 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 let (key, value) = if let Some(v) = iter.next() {
794 v
795 } else {
796 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)] 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 let item = if let Some(v) = iter.next() {
836 v
837 } else {
838 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}