1use std::cell::RefCell;
34use std::collections::VecDeque;
35use std::fmt::Display;
36use std::iter::Peekable;
37use std::rc::Rc;
38use std::rc::Weak;
39
40use super::common::Ranged;
41use crate::ParseOptions;
42use crate::ast;
43use crate::errors::ParseError;
44use crate::parse_to_ast;
45use crate::string::ParseStringErrorKind;
46
47mod input;
48
49pub use input::*;
50
51macro_rules! add_root_node_method {
52 () => {
53 pub fn root_node(&self) -> Option<CstRootNode> {
58 self
59 .ancestors()
60 .filter_map(|parent| match parent {
61 CstContainerNode::Root(node) => Some(node),
62 _ => None,
63 })
64 .next()
65 }
66 };
67}
68
69macro_rules! add_parent_info_methods {
70 () => {
71 pub fn parent(&self) -> Option<CstContainerNode> {
76 self.parent_info().map(|p| p.parent.as_container_node())
77 }
78
79 pub fn ancestors(&self) -> impl Iterator<Item = CstContainerNode> {
81 AncestorIterator::new(self.clone().into())
82 }
83
84 pub fn child_index(&self) -> usize {
87 self.parent_info().map(|p| p.child_index).unwrap_or(0)
88 }
89
90 pub fn previous_sibling(&self) -> Option<CstNode> {
92 let parent_info = self.parent_info()?;
93 if parent_info.child_index == 0 {
94 return None;
95 }
96 parent_info
97 .parent
98 .as_container_node()
99 .child_at_index(parent_info.child_index - 1)
100 }
101
102 pub fn previous_siblings(&self) -> impl Iterator<Item = CstNode> {
105 PreviousSiblingIterator::new(self.clone().into())
106 }
107
108 pub fn next_sibling(&self) -> Option<CstNode> {
110 let parent_info = self.parent_info()?;
111 parent_info
112 .parent
113 .as_container_node()
114 .child_at_index(parent_info.child_index + 1)
115 }
116
117 pub fn next_siblings(&self) -> impl Iterator<Item = CstNode> {
120 NextSiblingIterator::new(self.clone().into())
121 }
122
123 pub fn indent_text(&self) -> Option<String> {
125 indent_text(&self.clone().into())
126 }
127
128 pub fn trailing_comma(&self) -> Option<CstToken> {
130 find_trailing_comma(&self.clone().into())
131 }
132
133 pub fn uses_trailing_commas(&self) -> bool {
135 uses_trailing_commas(self.clone().into())
136 }
137 };
138}
139
140fn find_trailing_comma(node: &CstNode) -> Option<CstToken> {
141 for next_sibling in node.next_siblings() {
142 match next_sibling {
143 CstNode::Container(_) => return None,
144 CstNode::Leaf(leaf) => match leaf {
145 CstLeafNode::BooleanLit(_)
146 | CstLeafNode::NullKeyword(_)
147 | CstLeafNode::NumberLit(_)
148 | CstLeafNode::StringLit(_)
149 | CstLeafNode::WordLit(_) => return None,
150 CstLeafNode::Token(token) => {
151 if token.value() == ',' {
152 return Some(token);
153 } else {
154 return None;
155 }
156 }
157 CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
158 }
160 },
161 }
162 }
163
164 None
165}
166
167macro_rules! add_parent_methods {
168 () => {
169 add_parent_info_methods!();
170
171 fn parent_info(&self) -> Option<ParentInfo> {
172 self.0.borrow().parent.clone()
173 }
174
175 fn set_parent(&self, parent: Option<ParentInfo>) {
176 self.0.borrow_mut().parent = parent;
177 }
178 };
179}
180
181macro_rules! impl_from_leaf_or_container {
182 ($node_name:ident, $variant:ident, $leaf_or_container:ident, $leaf_or_container_variant:ident) => {
183 impl From<$node_name> for CstNode {
184 fn from(value: $node_name) -> Self {
185 CstNode::$leaf_or_container_variant($leaf_or_container::$variant(value))
186 }
187 }
188
189 impl From<$node_name> for $leaf_or_container {
190 fn from(value: $node_name) -> Self {
191 $leaf_or_container::$variant(value)
192 }
193 }
194 };
195}
196
197macro_rules! impl_container_methods {
198 ($node_name:ident, $variant:ident) => {
199 impl_from_leaf_or_container!($node_name, $variant, CstContainerNode, Container);
200
201 impl $node_name {
202 add_parent_methods!();
203
204 pub fn children(&self) -> Vec<CstNode> {
206 self.0.borrow().value.clone()
207 }
208
209 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
211 self
212 .0
213 .borrow()
214 .value
215 .iter()
216 .filter(|n| !n.is_trivia() && !n.is_token())
217 .cloned()
218 .collect()
219 }
220
221 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
223 self.0.borrow().value.get(index).cloned()
224 }
225
226 fn remove_child_set_no_parent(&self, index: usize) {
227 let mut inner = self.0.borrow_mut();
228 if index < inner.value.len() {
229 let container = self.clone().into();
230 let child = inner.value.remove(index);
231 child.set_parent(None);
232
233 for index in index..inner.value.len() {
235 inner.value[index].set_parent(Some(ParentInfo {
236 parent: WeakParent::from_container(&container),
237 child_index: index,
238 }));
239 }
240 }
241 }
242 }
243 };
244}
245
246macro_rules! impl_leaf_methods {
247 ($node_name:ident, $variant:ident) => {
248 impl_from_leaf_or_container!($node_name, $variant, CstLeafNode, Leaf);
249
250 impl $node_name {
251 add_parent_methods!();
252 add_root_node_method!();
253 }
254 };
255}
256
257#[derive(Debug, Clone)]
258enum WeakParent {
259 Root(Weak<CstRootNodeInner>),
260 Object(Weak<CstObjectInner>),
261 ObjectProp(Weak<CstObjectPropInner>),
262 Array(Weak<CstArrayInner>),
263}
264
265impl WeakParent {
266 pub fn from_container(container: &CstContainerNode) -> Self {
267 match container {
268 CstContainerNode::Root(node) => WeakParent::Root(Rc::downgrade(&node.0)),
269 CstContainerNode::Object(node) => WeakParent::Object(Rc::downgrade(&node.0)),
270 CstContainerNode::ObjectProp(node) => WeakParent::ObjectProp(Rc::downgrade(&node.0)),
271 CstContainerNode::Array(node) => WeakParent::Array(Rc::downgrade(&node.0)),
272 }
273 }
274
275 pub fn as_container_node(&self) -> CstContainerNode {
276 const PANIC_MSG: &str = "Programming error. Ensure you keep around the RootNode for the duration of using the CST.";
280 match self {
281 WeakParent::Root(weak) => CstRootNode(weak.upgrade().expect(PANIC_MSG)).into(),
282 WeakParent::Object(weak) => CstObject(weak.upgrade().expect(PANIC_MSG)).into(),
283 WeakParent::ObjectProp(weak) => CstObjectProp(weak.upgrade().expect(PANIC_MSG)).into(),
284 WeakParent::Array(weak) => CstArray(weak.upgrade().expect(PANIC_MSG)).into(),
285 }
286 }
287}
288
289#[derive(Clone, Debug)]
290struct ParentInfo {
291 pub parent: WeakParent,
292 pub child_index: usize,
293}
294
295#[derive(Debug)]
296struct CstValueInner<T> {
297 parent: Option<ParentInfo>,
298 value: T,
299}
300
301impl<T> CstValueInner<T> {
302 fn new(value: T) -> Rc<RefCell<Self>> {
303 Rc::new(RefCell::new(CstValueInner { parent: None, value }))
304 }
305}
306
307type CstChildrenInner = CstValueInner<Vec<CstNode>>;
308
309#[derive(Debug, Clone)]
311pub enum CstNode {
312 Container(CstContainerNode),
313 Leaf(CstLeafNode),
314}
315
316impl CstNode {
317 add_parent_info_methods!();
318 add_root_node_method!();
319
320 pub fn is_trivia(&self) -> bool {
322 match self {
323 CstNode::Leaf(leaf) => match leaf {
324 CstLeafNode::BooleanLit(_)
325 | CstLeafNode::NullKeyword(_)
326 | CstLeafNode::NumberLit(_)
327 | CstLeafNode::StringLit(_)
328 | CstLeafNode::Token(_)
329 | CstLeafNode::WordLit(_) => false,
330 CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => true,
331 },
332 CstNode::Container(_) => false,
333 }
334 }
335
336 pub fn leading_comments_same_line(&self) -> impl Iterator<Item = CstComment> {
338 self
339 .previous_siblings()
340 .take_while(|n| n.is_whitespace() || n.is_comment())
341 .filter_map(|n| match n {
342 CstNode::Leaf(CstLeafNode::Comment(comment)) => Some(comment.clone()),
343 _ => None,
344 })
345 }
346
347 pub fn trailing_comments_same_line(&self) -> impl Iterator<Item = CstComment> {
351 for sibling in self.next_siblings() {
353 if sibling.is_newline() {
354 break;
355 } else if !sibling.is_comment() && !sibling.is_whitespace() {
356 return Box::new(std::iter::empty()) as Box<dyn Iterator<Item = CstComment>>;
357 }
358 }
359
360 Box::new(
361 self
362 .next_siblings()
363 .take_while(|n| n.is_whitespace() || n.is_comment())
364 .filter_map(|n| match n {
365 CstNode::Leaf(CstLeafNode::Comment(comment)) => Some(comment.clone()),
366 _ => None,
367 }),
368 )
369 }
370
371 pub fn is_newline(&self) -> bool {
373 matches!(self, CstNode::Leaf(CstLeafNode::Newline(_)))
374 }
375
376 pub fn is_comma(&self) -> bool {
378 match self {
379 CstNode::Leaf(CstLeafNode::Token(t)) => t.value() == ',',
380 _ => false,
381 }
382 }
383
384 pub fn is_comment(&self) -> bool {
386 matches!(self, CstNode::Leaf(CstLeafNode::Comment(_)))
387 }
388
389 pub fn is_token(&self) -> bool {
391 matches!(self, CstNode::Leaf(CstLeafNode::Token(_)))
392 }
393
394 pub fn is_whitespace(&self) -> bool {
396 matches!(self, CstNode::Leaf(CstLeafNode::Whitespace(_)))
397 }
398
399 pub fn token_char(&self) -> Option<char> {
401 match self {
402 CstNode::Leaf(CstLeafNode::Token(token)) => Some(token.value()),
403 _ => None,
404 }
405 }
406
407 pub fn children(&self) -> Vec<CstNode> {
409 match self {
410 CstNode::Container(n) => n.children(),
411 CstNode::Leaf(_) => Vec::new(),
412 }
413 }
414
415 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
417 match self {
418 CstNode::Container(n) => n.children_exclude_trivia_and_tokens(),
419 CstNode::Leaf(_) => Vec::new(),
420 }
421 }
422
423 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
425 match self {
426 CstNode::Container(n) => n.child_at_index(index),
427 CstNode::Leaf(_) => None,
428 }
429 }
430
431 pub fn element_index(&self) -> Option<usize> {
435 let child_index = self.child_index();
436 let array = self.parent()?.as_array()?;
437 array.elements().iter().position(|p| p.child_index() == child_index)
438 }
439
440 pub fn as_root_node(&self) -> Option<CstRootNode> {
442 match self {
443 CstNode::Container(CstContainerNode::Root(node)) => Some(node.clone()),
444 _ => None,
445 }
446 }
447
448 pub fn as_object(&self) -> Option<CstObject> {
450 match self {
451 CstNode::Container(CstContainerNode::Object(node)) => Some(node.clone()),
453 _ => None,
454 }
455 }
456
457 pub fn as_array(&self) -> Option<CstArray> {
459 match self {
460 CstNode::Container(CstContainerNode::Array(node)) => Some(node.clone()),
461 _ => None,
462 }
463 }
464
465 pub fn as_object_prop(&self) -> Option<CstObjectProp> {
467 match self {
468 CstNode::Container(CstContainerNode::ObjectProp(node)) => Some(node.clone()),
469 _ => None,
470 }
471 }
472
473 pub fn as_boolean_lit(&self) -> Option<CstBooleanLit> {
475 match self {
476 CstNode::Leaf(CstLeafNode::BooleanLit(node)) => Some(node.clone()),
477 _ => None,
478 }
479 }
480
481 pub fn as_null_keyword(&self) -> Option<CstNullKeyword> {
483 match self {
484 CstNode::Leaf(CstLeafNode::NullKeyword(node)) => Some(node.clone()),
485 _ => None,
486 }
487 }
488
489 pub fn as_number_lit(&self) -> Option<CstNumberLit> {
491 match self {
492 CstNode::Leaf(CstLeafNode::NumberLit(node)) => Some(node.clone()),
493 _ => None,
494 }
495 }
496
497 pub fn as_string_lit(&self) -> Option<CstStringLit> {
499 match self {
500 CstNode::Leaf(CstLeafNode::StringLit(node)) => Some(node.clone()),
501 _ => None,
502 }
503 }
504
505 pub fn as_word_lit(&self) -> Option<CstWordLit> {
507 match self {
508 CstNode::Leaf(CstLeafNode::WordLit(node)) => Some(node.clone()),
509 _ => None,
510 }
511 }
512
513 pub fn as_token(&self) -> Option<CstToken> {
515 match self {
516 CstNode::Leaf(CstLeafNode::Token(node)) => Some(node.clone()),
517 _ => None,
518 }
519 }
520
521 pub fn as_newline(&self) -> Option<CstNewline> {
523 match self {
524 CstNode::Leaf(CstLeafNode::Newline(node)) => Some(node.clone()),
525 _ => None,
526 }
527 }
528
529 pub fn as_whitespace(&self) -> Option<CstWhitespace> {
531 match self {
532 CstNode::Leaf(CstLeafNode::Whitespace(node)) => Some(node.clone()),
533 _ => None,
534 }
535 }
536
537 pub fn as_comment(&self) -> Option<CstComment> {
539 match self {
540 CstNode::Leaf(CstLeafNode::Comment(node)) => Some(node.clone()),
541 _ => None,
542 }
543 }
544
545 pub fn remove(self) {
549 match self {
550 CstNode::Container(n) => n.remove(),
551 CstNode::Leaf(n) => n.remove(),
552 }
553 }
554
555 fn parent_info(&self) -> Option<ParentInfo> {
556 match self {
557 CstNode::Container(node) => node.parent_info(),
558 CstNode::Leaf(node) => node.parent_info(),
559 }
560 }
561
562 fn set_parent(&self, parent: Option<ParentInfo>) {
563 match self {
564 CstNode::Container(node) => node.set_parent(parent),
565 CstNode::Leaf(node) => node.set_parent(parent),
566 }
567 }
568
569 fn remove_raw(self) {
571 let Some(parent_info) = self.parent_info() else {
572 return; };
574 parent_info
575 .parent
576 .as_container_node()
577 .remove_child_set_no_parent(parent_info.child_index);
578 }
579
580 #[cfg(feature = "serde")]
602 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
603 match self {
604 CstNode::Container(container) => container.to_serde_value(),
605 CstNode::Leaf(leaf) => leaf.to_serde_value(),
606 }
607 }
608}
609
610impl Display for CstNode {
611 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
612 match self {
613 CstNode::Container(node) => node.fmt(f),
614 CstNode::Leaf(node) => node.fmt(f),
615 }
616 }
617}
618
619#[derive(Default, Debug, Clone)]
620struct StyleInfo {
621 pub uses_trailing_commas: bool,
622 pub newline_kind: CstNewlineKind,
623}
624
625#[derive(Debug, Clone)]
627pub enum CstContainerNode {
628 Root(CstRootNode),
629 Array(CstArray),
630 Object(CstObject),
631 ObjectProp(CstObjectProp),
632}
633
634impl CstContainerNode {
635 add_parent_info_methods!();
636 add_root_node_method!();
637
638 pub fn is_root(&self) -> bool {
640 matches!(self, CstContainerNode::Root(_))
641 }
642
643 pub fn is_array(&self) -> bool {
645 matches!(self, CstContainerNode::Array(_))
646 }
647
648 pub fn is_object(&self) -> bool {
650 matches!(self, CstContainerNode::Object(_))
651 }
652
653 pub fn is_object_prop(&self) -> bool {
655 matches!(self, CstContainerNode::ObjectProp(_))
656 }
657
658 pub fn as_root(&self) -> Option<CstRootNode> {
660 match self {
661 CstContainerNode::Root(node) => Some(node.clone()),
662 _ => None,
663 }
664 }
665
666 pub fn as_array(&self) -> Option<CstArray> {
668 match self {
669 CstContainerNode::Array(node) => Some(node.clone()),
670 _ => None,
671 }
672 }
673
674 pub fn as_object(&self) -> Option<CstObject> {
676 match self {
677 CstContainerNode::Object(node) => Some(node.clone()),
678 _ => None,
679 }
680 }
681
682 pub fn as_object_prop(&self) -> Option<CstObjectProp> {
684 match self {
685 CstContainerNode::ObjectProp(node) => Some(node.clone()),
686 _ => None,
687 }
688 }
689
690 pub fn children(&self) -> Vec<CstNode> {
692 match self {
693 CstContainerNode::Root(n) => n.children(),
694 CstContainerNode::Object(n) => n.children(),
695 CstContainerNode::ObjectProp(n) => n.children(),
696 CstContainerNode::Array(n) => n.children(),
697 }
698 }
699
700 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
702 match self {
703 CstContainerNode::Root(n) => n.children_exclude_trivia_and_tokens(),
704 CstContainerNode::Object(n) => n.children_exclude_trivia_and_tokens(),
705 CstContainerNode::ObjectProp(n) => n.children_exclude_trivia_and_tokens(),
706 CstContainerNode::Array(n) => n.children_exclude_trivia_and_tokens(),
707 }
708 }
709
710 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
712 match self {
713 CstContainerNode::Root(node) => node.child_at_index(index),
714 CstContainerNode::Object(node) => node.child_at_index(index),
715 CstContainerNode::ObjectProp(node) => node.child_at_index(index),
716 CstContainerNode::Array(node) => node.child_at_index(index),
717 }
718 }
719
720 fn remove_child_set_no_parent(&self, index: usize) {
721 match self {
722 CstContainerNode::Root(n) => n.remove_child_set_no_parent(index),
723 CstContainerNode::Object(n) => n.remove_child_set_no_parent(index),
724 CstContainerNode::ObjectProp(n) => n.remove_child_set_no_parent(index),
725 CstContainerNode::Array(n) => n.remove_child_set_no_parent(index),
726 }
727 }
728
729 pub fn remove(self) {
731 match self {
732 CstContainerNode::Root(n) => n.clear_children(),
733 CstContainerNode::Object(n) => n.remove(),
734 CstContainerNode::ObjectProp(n) => n.remove(),
735 CstContainerNode::Array(n) => n.remove(),
736 }
737 }
738
739 fn parent_info(&self) -> Option<ParentInfo> {
740 match self {
741 CstContainerNode::Root(node) => node.parent_info(),
742 CstContainerNode::Object(node) => node.parent_info(),
743 CstContainerNode::ObjectProp(node) => node.parent_info(),
744 CstContainerNode::Array(node) => node.parent_info(),
745 }
746 }
747
748 fn set_parent(&self, parent: Option<ParentInfo>) {
749 match self {
750 CstContainerNode::Root(node) => node.set_parent(parent),
751 CstContainerNode::Object(node) => node.set_parent(parent),
752 CstContainerNode::ObjectProp(node) => node.set_parent(parent),
753 CstContainerNode::Array(node) => node.set_parent(parent),
754 }
755 }
756
757 #[inline(always)]
758 fn raw_append_child(&self, child: CstNode) {
759 self.raw_insert_child(None, child);
760 }
761
762 #[inline(always)]
763 fn raw_insert_child(&self, index: Option<&mut usize>, child: CstNode) {
764 self.raw_insert_children(index, vec![child]);
765 }
766
767 #[inline(always)]
768 fn raw_append_children(&self, children: Vec<CstNode>) {
769 self.raw_insert_children(None, children);
770 }
771
772 fn raw_insert_children(&self, index: Option<&mut usize>, children: Vec<CstNode>) {
773 if children.is_empty() {
774 return;
775 }
776
777 let weak_parent = WeakParent::from_container(self);
778 let mut container = match self {
779 CstContainerNode::Root(node) => node.0.borrow_mut(),
780 CstContainerNode::Object(node) => node.0.borrow_mut(),
781 CstContainerNode::ObjectProp(node) => node.0.borrow_mut(),
782 CstContainerNode::Array(node) => node.0.borrow_mut(),
783 };
784 let insert_index = index.as_ref().map(|i| **i).unwrap_or(container.value.len());
785 if let Some(i) = index {
786 *i += children.len();
787 }
788 container.value.splice(insert_index..insert_index, children);
789
790 for (i, child) in container.value.iter().enumerate().skip(insert_index) {
792 child.set_parent(Some(ParentInfo {
793 parent: weak_parent.clone(),
794 child_index: i,
795 }));
796 }
797 }
798
799 fn raw_insert_value_with_internal_indent(
800 &self,
801 insert_index: Option<&mut usize>,
802 value: InsertValue,
803 style_info: &StyleInfo,
804 indents: &Indents,
805 ) {
806 match value {
807 InsertValue::Value(value) => {
808 let is_multiline = value.force_multiline();
809 match value {
810 CstInputValue::Null => {
811 self.raw_insert_child(insert_index, CstLeafNode::NullKeyword(CstNullKeyword::new()).into());
812 }
813 CstInputValue::Bool(value) => {
814 self.raw_insert_child(insert_index, CstLeafNode::BooleanLit(CstBooleanLit::new(value)).into());
815 }
816 CstInputValue::Number(value) => {
817 self.raw_insert_child(insert_index, CstLeafNode::NumberLit(CstNumberLit::new(value)).into());
818 }
819 CstInputValue::String(value) => {
820 self.raw_insert_child(
821 insert_index,
822 CstLeafNode::StringLit(CstStringLit::new_escaped(&value)).into(),
823 );
824 }
825 CstInputValue::Array(elements) => {
826 let array_node: CstContainerNode = CstArray::new_no_tokens().into();
827 self.raw_insert_child(insert_index, array_node.clone().into());
828
829 array_node.raw_append_child(CstToken::new('[').into());
830 if !elements.is_empty() {
831 let indents = indents.indent();
832 let mut elements = elements.into_iter().peekable();
833 while let Some(value) = elements.next() {
834 if is_multiline {
835 array_node.raw_insert_children(
836 None,
837 vec![
838 CstNewline::new(style_info.newline_kind).into(),
839 CstWhitespace::new(indents.current_indent.clone()).into(),
840 ],
841 );
842 }
843
844 array_node.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, &indents);
845
846 if style_info.uses_trailing_commas && is_multiline || elements.peek().is_some() {
847 if is_multiline {
848 array_node.raw_append_child(CstToken::new(',').into());
849 } else {
850 array_node.raw_insert_children(
851 None,
852 vec![CstToken::new(',').into(), CstWhitespace::new(" ".to_string()).into()],
853 );
854 }
855 }
856 }
857 }
858
859 if is_multiline {
860 array_node.raw_append_children(vec![
861 CstNewline::new(style_info.newline_kind).into(),
862 CstWhitespace::new(indents.current_indent.clone()).into(),
863 ]);
864 }
865
866 array_node.raw_append_child(CstToken::new(']').into());
867 }
868 CstInputValue::Object(properties) => {
869 let object_node: CstContainerNode = CstObject::new_no_tokens().into();
870 self.raw_insert_child(insert_index, object_node.clone().into());
871
872 object_node.raw_append_child(CstToken::new('{').into());
873
874 if !properties.is_empty() {
875 {
876 let indents = indents.indent();
877 let mut properties = properties.into_iter().peekable();
878 while let Some((prop_name, value)) = properties.next() {
879 object_node.raw_append_child(CstNewline::new(style_info.newline_kind).into());
880 object_node.raw_append_child(CstWhitespace::new(indents.current_indent.clone()).into());
881 object_node.raw_insert_value_with_internal_indent(
882 None,
883 InsertValue::Property(&prop_name, value),
884 style_info,
885 &indents,
886 );
887 if style_info.uses_trailing_commas || properties.peek().is_some() {
888 object_node.raw_append_child(CstToken::new(',').into());
889 }
890 }
891 }
892
893 object_node.raw_append_children(vec![
894 CstNewline::new(style_info.newline_kind).into(),
895 CstWhitespace::new(indents.current_indent.clone()).into(),
896 ]);
897 }
898
899 object_node.raw_append_child(CstToken::new('}').into());
900 }
901 }
902 }
903 InsertValue::Property(prop_name, value) => {
904 let prop = CstContainerNode::ObjectProp(CstObjectProp::new());
905 self.raw_insert_child(insert_index, prop.clone().into());
906 prop.raw_insert_children(
907 None,
908 vec![
909 CstStringLit::new_escaped(prop_name).into(),
910 CstToken::new(':').into(),
911 CstWhitespace::new(" ".to_string()).into(),
912 ],
913 );
914 prop.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, indents);
915 }
916 }
917 }
918
919 #[cfg(feature = "serde")]
923 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
924 match self {
925 CstContainerNode::Root(node) => node.to_serde_value(),
926 CstContainerNode::Array(node) => node.to_serde_value(),
927 CstContainerNode::Object(node) => node.to_serde_value(),
928 CstContainerNode::ObjectProp(node) => node.to_serde_value(),
929 }
930 }
931}
932
933impl From<CstContainerNode> for CstNode {
934 fn from(value: CstContainerNode) -> Self {
935 CstNode::Container(value)
936 }
937}
938
939impl Display for CstContainerNode {
940 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
941 match self {
942 CstContainerNode::Root(node) => node.fmt(f),
943 CstContainerNode::Object(node) => node.fmt(f),
944 CstContainerNode::ObjectProp(node) => node.fmt(f),
945 CstContainerNode::Array(node) => node.fmt(f),
946 }
947 }
948}
949
950#[derive(Debug, Clone)]
952pub enum CstLeafNode {
953 BooleanLit(CstBooleanLit),
954 NullKeyword(CstNullKeyword),
955 NumberLit(CstNumberLit),
956 StringLit(CstStringLit),
957 WordLit(CstWordLit),
958 Token(CstToken),
959 Whitespace(CstWhitespace),
960 Newline(CstNewline),
961 Comment(CstComment),
962}
963
964impl CstLeafNode {
965 add_parent_info_methods!();
966 add_root_node_method!();
967
968 pub fn remove(self) {
970 match self {
971 CstLeafNode::BooleanLit(n) => n.remove(),
972 CstLeafNode::NullKeyword(n) => n.remove(),
973 CstLeafNode::NumberLit(n) => n.remove(),
974 CstLeafNode::StringLit(n) => n.remove(),
975 CstLeafNode::WordLit(n) => n.remove(),
976 CstLeafNode::Token(n) => n.remove(),
977 CstLeafNode::Whitespace(n) => n.remove(),
978 CstLeafNode::Newline(n) => n.remove(),
979 CstLeafNode::Comment(n) => n.remove(),
980 }
981 }
982
983 fn parent_info(&self) -> Option<ParentInfo> {
984 match self {
985 CstLeafNode::BooleanLit(node) => node.parent_info(),
986 CstLeafNode::NullKeyword(node) => node.parent_info(),
987 CstLeafNode::NumberLit(node) => node.parent_info(),
988 CstLeafNode::StringLit(node) => node.parent_info(),
989 CstLeafNode::WordLit(node) => node.parent_info(),
990 CstLeafNode::Token(node) => node.parent_info(),
991 CstLeafNode::Whitespace(node) => node.parent_info(),
992 CstLeafNode::Newline(node) => node.parent_info(),
993 CstLeafNode::Comment(node) => node.parent_info(),
994 }
995 }
996
997 fn set_parent(&self, parent: Option<ParentInfo>) {
998 match self {
999 CstLeafNode::BooleanLit(node) => node.set_parent(parent),
1000 CstLeafNode::NullKeyword(node) => node.set_parent(parent),
1001 CstLeafNode::NumberLit(node) => node.set_parent(parent),
1002 CstLeafNode::StringLit(node) => node.set_parent(parent),
1003 CstLeafNode::WordLit(node) => node.set_parent(parent),
1004 CstLeafNode::Token(node) => node.set_parent(parent),
1005 CstLeafNode::Whitespace(node) => node.set_parent(parent),
1006 CstLeafNode::Newline(node) => node.set_parent(parent),
1007 CstLeafNode::Comment(node) => node.set_parent(parent),
1008 }
1009 }
1010
1011 #[cfg(feature = "serde")]
1015 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1016 match self {
1017 CstLeafNode::BooleanLit(node) => node.to_serde_value(),
1018 CstLeafNode::NullKeyword(node) => node.to_serde_value(),
1019 CstLeafNode::NumberLit(node) => node.to_serde_value(),
1020 CstLeafNode::StringLit(node) => node.to_serde_value(),
1021 CstLeafNode::WordLit(_)
1022 | CstLeafNode::Token(_)
1023 | CstLeafNode::Whitespace(_)
1024 | CstLeafNode::Newline(_)
1025 | CstLeafNode::Comment(_) => None,
1026 }
1027 }
1028}
1029
1030impl Display for CstLeafNode {
1031 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1032 match self {
1033 CstLeafNode::BooleanLit(node) => node.fmt(f),
1034 CstLeafNode::NullKeyword(node) => node.fmt(f),
1035 CstLeafNode::NumberLit(node) => node.fmt(f),
1036 CstLeafNode::StringLit(node) => node.fmt(f),
1037 CstLeafNode::WordLit(node) => node.fmt(f),
1038 CstLeafNode::Token(node) => node.fmt(f),
1039 CstLeafNode::Whitespace(node) => node.fmt(f),
1040 CstLeafNode::Newline(node) => node.fmt(f),
1041 CstLeafNode::Comment(node) => node.fmt(f),
1042 }
1043 }
1044}
1045
1046impl From<CstLeafNode> for CstNode {
1047 fn from(value: CstLeafNode) -> Self {
1048 CstNode::Leaf(value)
1049 }
1050}
1051
1052#[derive(Default, Debug, Clone, Copy)]
1054pub enum TrailingCommaMode {
1055 #[default]
1057 Never,
1058 IfMultiline,
1060}
1061
1062type CstRootNodeInner = RefCell<CstChildrenInner>;
1063
1064#[derive(Debug, Clone)]
1068pub struct CstRootNode(Rc<CstRootNodeInner>);
1069
1070impl_container_methods!(CstRootNode, Root);
1071
1072impl CstRootNode {
1073 pub fn parse(text: &str, parse_options: &ParseOptions) -> Result<Self, ParseError> {
1108 let parse_result = parse_to_ast(
1109 text,
1110 &crate::CollectOptions {
1111 comments: crate::CommentCollectionStrategy::AsTokens,
1112 tokens: true,
1113 },
1114 parse_options,
1115 )?;
1116
1117 Ok(
1118 CstBuilder {
1119 text,
1120 tokens: parse_result.tokens.unwrap().into_iter().collect(),
1121 }
1122 .build(parse_result.value),
1123 )
1124 }
1125
1126 pub fn single_indent_text(&self) -> Option<String> {
1128 let root_value = self.value()?;
1129 let first_non_trivia_child = root_value.children_exclude_trivia_and_tokens().first()?.clone();
1130 let mut last_whitespace = None;
1131 for previous_trivia in first_non_trivia_child.previous_siblings() {
1132 match previous_trivia {
1133 CstNode::Leaf(CstLeafNode::Whitespace(whitespace)) => {
1134 last_whitespace = Some(whitespace);
1135 }
1136 CstNode::Leaf(CstLeafNode::Newline(_)) => {
1137 return last_whitespace.map(|whitespace| whitespace.0.borrow().value.clone());
1138 }
1139 _ => {
1140 last_whitespace = None;
1141 }
1142 }
1143 }
1144 None
1145 }
1146
1147 pub fn newline_kind(&self) -> CstNewlineKind {
1149 let mut current_children: VecDeque<CstContainerNode> = VecDeque::from([self.clone().into()]);
1150 while let Some(child) = current_children.pop_front() {
1151 for child in child.children() {
1152 if let CstNode::Container(child) = child {
1153 current_children.push_back(child);
1154 } else if let CstNode::Leaf(CstLeafNode::Newline(node)) = child {
1155 return node.kind();
1156 }
1157 }
1158 }
1159 CstNewlineKind::LineFeed
1160 }
1161
1162 pub fn value(&self) -> Option<CstNode> {
1164 for child in &self.0.borrow().value {
1165 if !child.is_trivia() {
1166 return Some(child.clone());
1167 }
1168 }
1169 None
1170 }
1171
1172 pub fn set_value(&self, root_value: CstInputValue) {
1174 let container: CstContainerNode = self.clone().into();
1175 let style_info = StyleInfo {
1176 newline_kind: self.newline_kind(),
1177 uses_trailing_commas: uses_trailing_commas(self.clone().into()),
1178 };
1179 let indents = compute_indents(&self.clone().into());
1180 let mut insert_index = if let Some(root_value) = self.value() {
1181 let index = root_value.child_index();
1182 root_value.remove_raw();
1183 index
1184 } else {
1185 let children = self.children();
1186 let mut index = match children.last() {
1187 Some(CstNode::Leaf(CstLeafNode::Newline(_))) => children.len() - 1,
1188 _ => children.len(),
1189 };
1190 let previous_node = if index == 0 { None } else { children.get(index - 1) };
1191 if let Some(CstNode::Leaf(CstLeafNode::Comment(_))) = previous_node {
1192 container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1194 }
1195 if self.child_at_index(index).is_none() {
1196 container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1198 index -= 1;
1199 }
1200 index
1201 };
1202 container.raw_insert_value_with_internal_indent(
1203 Some(&mut insert_index),
1204 InsertValue::Value(root_value),
1205 &style_info,
1206 &indents,
1207 );
1208 }
1209
1210 pub fn object_value(&self) -> Option<CstObject> {
1212 self.value()?.as_object()
1213 }
1214
1215 pub fn object_value_or_create(&self) -> Option<CstObject> {
1221 match self.value() {
1222 Some(CstNode::Container(CstContainerNode::Object(node))) => Some(node),
1223 Some(_) => None,
1224 None => {
1225 self.set_value(CstInputValue::Object(Vec::new()));
1226 self.object_value()
1227 }
1228 }
1229 }
1230
1231 pub fn object_value_or_set(&self) -> CstObject {
1236 match self.value() {
1237 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1238 _ => {
1239 self.set_value(CstInputValue::Object(Vec::new()));
1240 self.object_value().unwrap()
1241 }
1242 }
1243 }
1244
1245 pub fn array_value(&self) -> Option<CstArray> {
1247 self.value()?.as_array()
1248 }
1249
1250 pub fn array_value_or_create(&self) -> Option<CstArray> {
1256 match self.value() {
1257 Some(CstNode::Container(CstContainerNode::Array(node))) => Some(node),
1258 Some(_) => None,
1259 None => {
1260 self.set_value(CstInputValue::Array(Vec::new()));
1261 self.array_value()
1262 }
1263 }
1264 }
1265
1266 pub fn array_value_or_set(&self) -> CstArray {
1271 match self.value() {
1272 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1273 _ => {
1274 self.set_value(CstInputValue::Array(Vec::new()));
1275 self.array_value().unwrap()
1276 }
1277 }
1278 }
1279
1280 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1286 let Some(value) = self.value() else {
1287 return;
1288 };
1289
1290 match value {
1291 CstNode::Container(container) => match container {
1292 CstContainerNode::Array(n) => n.set_trailing_commas(mode),
1293 CstContainerNode::Object(n) => n.set_trailing_commas(mode),
1294 _ => {}
1295 },
1296 CstNode::Leaf(_) => {}
1297 }
1298 }
1299
1300 pub fn clear_children(&self) {
1302 let children = std::mem::take(&mut self.0.borrow_mut().value);
1303 for child in children {
1304 child.set_parent(None);
1305 }
1306 }
1307
1308 #[cfg(feature = "serde")]
1312 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1313 self.value()?.to_serde_value()
1314 }
1315}
1316
1317impl Display for CstRootNode {
1318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1319 for child in &self.0.borrow().value {
1320 write!(f, "{}", child)?;
1321 }
1322 Ok(())
1323 }
1324}
1325
1326#[derive(Debug, Clone)]
1328pub struct CstStringLit(Rc<RefCell<CstValueInner<String>>>);
1329
1330impl_leaf_methods!(CstStringLit, StringLit);
1331
1332impl CstStringLit {
1333 fn new(value: String) -> Self {
1334 Self(CstValueInner::new(value))
1335 }
1336
1337 fn new_escaped(value: &str) -> Self {
1338 Self::new(format!("\"{}\"", value.replace("\"", "\\\"")))
1339 }
1340
1341 pub fn set_raw_value(&self, value: String) {
1343 self.0.borrow_mut().value = value;
1344 }
1345
1346 pub fn raw_value(&self) -> String {
1348 self.0.borrow().value.clone()
1349 }
1350
1351 pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
1353 let inner = self.0.borrow();
1354 crate::string::parse_string(&inner.value)
1355 .map(|value| value.into_owned())
1356 .map_err(|err| err.kind)
1357 }
1358
1359 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1361 replace_with(self.into(), InsertValue::Value(replacement))
1362 }
1363
1364 pub fn remove(self) {
1366 remove_comma_separated(self.into())
1367 }
1368
1369 #[cfg(feature = "serde")]
1371 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1372 self.decoded_value().ok().map(serde_json::Value::String)
1373 }
1374}
1375
1376impl Display for CstStringLit {
1377 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1378 write!(f, "{}", self.0.borrow().value)
1379 }
1380}
1381
1382#[derive(Debug, Clone)]
1384pub struct CstWordLit(Rc<RefCell<CstValueInner<String>>>);
1385
1386impl_leaf_methods!(CstWordLit, WordLit);
1387
1388impl CstWordLit {
1389 fn new(value: String) -> Self {
1390 Self(CstValueInner::new(value))
1391 }
1392
1393 pub fn set_raw_value(&self, value: String) {
1395 self.0.borrow_mut().value = value;
1396 }
1397
1398 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1400 replace_with(self.into(), InsertValue::Value(replacement))
1401 }
1402
1403 pub fn remove(self) {
1405 remove_comma_separated(self.into())
1406 }
1407}
1408
1409impl Display for CstWordLit {
1410 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1411 write!(f, "{}", self.0.borrow().value)
1412 }
1413}
1414
1415#[derive(Debug, Clone)]
1416pub struct CstNumberLit(Rc<RefCell<CstValueInner<String>>>);
1417
1418impl_leaf_methods!(CstNumberLit, NumberLit);
1419
1420impl CstNumberLit {
1421 fn new(value: String) -> Self {
1422 Self(CstValueInner::new(value))
1423 }
1424
1425 pub fn set_raw_value(&self, value: String) {
1427 self.0.borrow_mut().value = value;
1428 }
1429
1430 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1432 replace_with(self.into(), InsertValue::Value(replacement))
1433 }
1434
1435 pub fn remove(self) {
1437 remove_comma_separated(self.into())
1438 }
1439
1440 #[cfg(feature = "serde")]
1442 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1443 use std::str::FromStr;
1444 let raw = self.0.borrow().value.clone();
1445
1446 let num_str = raw.trim_start_matches(['-', '+']);
1448 if num_str.len() > 2 && (num_str.starts_with("0x") || num_str.starts_with("0X")) {
1449 let hex_part = &num_str[2..];
1451 match i64::from_str_radix(hex_part, 16) {
1452 Ok(decimal_value) => {
1453 let final_value = if raw.starts_with('-') {
1454 -decimal_value
1455 } else {
1456 decimal_value
1457 };
1458 Some(serde_json::Value::Number(serde_json::Number::from(final_value)))
1459 }
1460 Err(_) => Some(serde_json::Value::String(raw)),
1461 }
1462 } else {
1463 let num_for_parsing = raw.trim_start_matches('+');
1465 match serde_json::Number::from_str(num_for_parsing) {
1466 Ok(number) => Some(serde_json::Value::Number(number)),
1467 Err(_) => Some(serde_json::Value::String(raw)),
1469 }
1470 }
1471 }
1472}
1473
1474impl Display for CstNumberLit {
1475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1476 write!(f, "{}", self.0.borrow().value)
1477 }
1478}
1479
1480#[derive(Debug, Clone)]
1482pub struct CstBooleanLit(Rc<RefCell<CstValueInner<bool>>>);
1483
1484impl_leaf_methods!(CstBooleanLit, BooleanLit);
1485
1486impl CstBooleanLit {
1487 fn new(value: bool) -> Self {
1488 Self(CstValueInner::new(value))
1489 }
1490
1491 pub fn value(&self) -> bool {
1493 self.0.borrow().value
1494 }
1495
1496 pub fn set_value(&self, value: bool) {
1498 self.0.borrow_mut().value = value;
1499 }
1500
1501 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1503 replace_with(self.into(), InsertValue::Value(replacement))
1504 }
1505
1506 pub fn remove(self) {
1508 remove_comma_separated(self.into())
1509 }
1510
1511 #[cfg(feature = "serde")]
1513 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1514 Some(serde_json::Value::Bool(self.value()))
1515 }
1516}
1517
1518impl Display for CstBooleanLit {
1519 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1520 if self.0.borrow().value {
1521 write!(f, "true")
1522 } else {
1523 write!(f, "false")
1524 }
1525 }
1526}
1527
1528#[derive(Debug, Clone)]
1530pub struct CstNullKeyword(Rc<RefCell<CstValueInner<()>>>);
1531
1532impl CstNullKeyword {
1533 fn new() -> Self {
1534 Self(CstValueInner::new(()))
1535 }
1536
1537 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1539 replace_with(self.into(), InsertValue::Value(replacement))
1540 }
1541
1542 pub fn remove(self) {
1544 remove_comma_separated(self.into())
1545 }
1546
1547 #[cfg(feature = "serde")]
1549 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1550 Some(serde_json::Value::Null)
1551 }
1552}
1553
1554impl_leaf_methods!(CstNullKeyword, NullKeyword);
1555
1556impl Display for CstNullKeyword {
1557 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1558 write!(f, "null")
1559 }
1560}
1561
1562type CstObjectInner = RefCell<CstChildrenInner>;
1563
1564#[derive(Debug, Clone)]
1566pub struct CstObject(Rc<CstObjectInner>);
1567
1568impl_container_methods!(CstObject, Object);
1569
1570impl CstObject {
1571 add_root_node_method!();
1572
1573 fn new_no_tokens() -> Self {
1574 Self(CstValueInner::new(Vec::new()))
1575 }
1576
1577 fn new_with_tokens() -> Self {
1578 let object = CstObject::new_no_tokens();
1579 let container: CstContainerNode = object.clone().into();
1580 container.raw_append_children(vec![CstToken::new('{').into(), CstToken::new('}').into()]);
1581 object
1582 }
1583
1584 pub fn array_value(&self, name: &str) -> Option<CstArray> {
1588 match self.get(name)?.value()? {
1589 CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1590 _ => None,
1591 }
1592 }
1593
1594 pub fn array_value_or_create(&self, name: &str) -> Option<CstArray> {
1601 match self.get(name) {
1602 Some(prop) => match prop.value()? {
1603 CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1604 _ => None,
1605 },
1606 None => {
1607 self.append(name, CstInputValue::Array(Vec::new()));
1608 self.array_value(name)
1609 }
1610 }
1611 }
1612
1613 pub fn array_value_or_set(&self, name: &str) -> CstArray {
1618 match self.get(name) {
1619 Some(prop) => match prop.value() {
1620 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1621 Some(node) => {
1622 let mut index = node.child_index();
1623 node.remove_raw();
1624 let container: CstContainerNode = prop.clone().into();
1625 let array = CstArray::new_with_tokens();
1626 container.raw_insert_child(Some(&mut index), array.clone().into());
1627 array
1628 }
1629 _ => {
1630 let mut index = prop.children().len();
1631 let container: CstContainerNode = prop.clone().into();
1632 let array = CstArray::new_with_tokens();
1633 container.raw_insert_child(Some(&mut index), array.clone().into());
1634 array
1635 }
1636 },
1637 None => {
1638 self.append(name, CstInputValue::Array(Vec::new()));
1639 self.array_value(name).unwrap()
1640 }
1641 }
1642 }
1643
1644 pub fn object_value(&self, name: &str) -> Option<CstObject> {
1648 match self.get(name)?.value()? {
1649 CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1650 _ => None,
1651 }
1652 }
1653
1654 pub fn object_value_or_create(&self, name: &str) -> Option<CstObject> {
1661 match self.get(name) {
1662 Some(prop) => match prop.value()? {
1663 CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1664 _ => None,
1665 },
1666 None => {
1667 self.append(name, CstInputValue::Object(Vec::new()));
1668 self.object_value(name)
1669 }
1670 }
1671 }
1672
1673 pub fn object_value_or_set(&self, name: &str) -> CstObject {
1678 match self.get(name) {
1679 Some(prop) => match prop.value() {
1680 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1681 Some(node) => {
1682 let mut index = node.child_index();
1683 node.remove_raw();
1684 let container: CstContainerNode = prop.clone().into();
1685 let object = CstObject::new_with_tokens();
1686 container.raw_insert_child(Some(&mut index), object.clone().into());
1687 object
1688 }
1689 _ => {
1690 let mut index = prop.children().len();
1691 let container: CstContainerNode = prop.clone().into();
1692 let object = CstObject::new_with_tokens();
1693 container.raw_insert_child(Some(&mut index), object.clone().into());
1694 object
1695 }
1696 },
1697 None => {
1698 self.append(name, CstInputValue::Object(Vec::new()));
1699 self.object_value(name).unwrap()
1700 }
1701 }
1702 }
1703
1704 pub fn get(&self, name: &str) -> Option<CstObjectProp> {
1708 for child in &self.0.borrow().value {
1709 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = child {
1710 let Some(prop_name) = prop.name() else {
1711 continue;
1712 };
1713 let Ok(prop_name_str) = prop_name.decoded_value() else {
1714 continue;
1715 };
1716 if prop_name_str == name {
1717 return Some(prop.clone());
1718 }
1719 }
1720 }
1721 None
1722 }
1723
1724 pub fn properties(&self) -> Vec<CstObjectProp> {
1726 self
1727 .0
1728 .borrow()
1729 .value
1730 .iter()
1731 .filter_map(|child| match child {
1732 CstNode::Container(CstContainerNode::ObjectProp(prop)) => Some(prop.clone()),
1733 _ => None,
1734 })
1735 .collect()
1736 }
1737
1738 pub fn append(&self, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1742 self.insert_or_append(None, prop_name, value)
1743 }
1744
1745 pub fn insert(&self, index: usize, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1749 self.insert_or_append(Some(index), prop_name, value)
1750 }
1751
1752 fn insert_or_append(&self, index: Option<usize>, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1753 self.ensure_multiline();
1754 insert_or_append_to_container(
1755 &CstContainerNode::Object(self.clone()),
1756 self.properties().into_iter().map(|c| c.into()).collect(),
1757 index,
1758 InsertValue::Property(prop_name, value),
1759 )
1760 .as_object_prop()
1761 .unwrap()
1762 }
1763
1764 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1766 replace_with(self.into(), InsertValue::Value(replacement))
1767 }
1768
1769 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1771 set_trailing_commas(
1772 mode,
1773 &self.clone().into(),
1774 self.properties().into_iter().map(|c| c.into()),
1775 );
1776 }
1777
1778 pub fn ensure_multiline(&self) {
1780 ensure_multiline(&self.clone().into());
1781 }
1782
1783 pub fn remove(self) {
1785 remove_comma_separated(self.into())
1786 }
1787
1788 #[cfg(feature = "serde")]
1790 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1791 let mut map = serde_json::map::Map::new();
1792 for prop in self.properties() {
1793 if let (Some(name), Some(value)) = (prop.name_decoded(), prop.to_serde_value()) {
1794 map.insert(name, value);
1795 }
1796 }
1797 Some(serde_json::Value::Object(map))
1798 }
1799}
1800
1801impl Display for CstObject {
1802 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1803 for child in &self.0.borrow().value {
1804 write!(f, "{}", child)?;
1805 }
1806 Ok(())
1807 }
1808}
1809
1810type CstObjectPropInner = RefCell<CstChildrenInner>;
1811
1812#[derive(Debug, Clone)]
1814pub struct CstObjectProp(Rc<CstObjectPropInner>);
1815
1816impl_container_methods!(CstObjectProp, ObjectProp);
1817
1818impl CstObjectProp {
1819 add_root_node_method!();
1820
1821 fn new() -> Self {
1822 Self(CstValueInner::new(Vec::new()))
1823 }
1824
1825 pub fn name(&self) -> Option<ObjectPropName> {
1829 for child in &self.0.borrow().value {
1830 match child {
1831 CstNode::Leaf(CstLeafNode::StringLit(node)) => return Some(ObjectPropName::String(node.clone())),
1832 CstNode::Leaf(CstLeafNode::WordLit(node)) => return Some(ObjectPropName::Word(node.clone())),
1833 _ => {
1834 }
1836 }
1837 }
1838 None
1839 }
1840
1841 pub fn property_index(&self) -> usize {
1842 let child_index = self.child_index();
1843 let Some(parent) = self.parent().and_then(|p| p.as_object()) else {
1844 return 0;
1845 };
1846 parent
1847 .properties()
1848 .iter()
1849 .position(|p| p.child_index() == child_index)
1850 .unwrap_or(0)
1851 }
1852
1853 pub fn set_value(&self, replacement: CstInputValue) {
1854 let maybe_value = self.value();
1855 let mut value_index = maybe_value
1856 .as_ref()
1857 .map(|v| v.child_index())
1858 .unwrap_or_else(|| self.children().len());
1859 let container: CstContainerNode = self.clone().into();
1860 let indents = compute_indents(&container.clone().into());
1861 let style_info = &StyleInfo {
1862 newline_kind: container.root_node().map(|v| v.newline_kind()).unwrap_or_default(),
1863 uses_trailing_commas: uses_trailing_commas(maybe_value.unwrap_or_else(|| container.clone().into())),
1864 };
1865 self.remove_child_set_no_parent(value_index);
1866 container.raw_insert_value_with_internal_indent(
1867 Some(&mut value_index),
1868 InsertValue::Value(replacement),
1869 style_info,
1870 &indents,
1871 );
1872 }
1873
1874 pub fn value(&self) -> Option<CstNode> {
1878 let name = self.name()?;
1879 let parent_info = name.parent_info()?;
1880 let children = &self.0.borrow().value;
1881 let mut children = children[parent_info.child_index + 1..].iter();
1882
1883 for child in children.by_ref() {
1885 if let CstNode::Leaf(CstLeafNode::Token(token)) = child
1886 && token.value() == ':'
1887 {
1888 break;
1889 }
1890 }
1891
1892 for child in children {
1894 match child {
1895 CstNode::Leaf(leaf) => match leaf {
1896 CstLeafNode::BooleanLit(_)
1897 | CstLeafNode::NullKeyword(_)
1898 | CstLeafNode::NumberLit(_)
1899 | CstLeafNode::StringLit(_)
1900 | CstLeafNode::WordLit(_) => return Some(child.clone()),
1901 CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
1902 }
1904 },
1905 CstNode::Container(container) => match container {
1906 CstContainerNode::Object(_) | CstContainerNode::Array(_) => return Some(child.clone()),
1907 CstContainerNode::Root(_) | CstContainerNode::ObjectProp(_) => return None,
1908 },
1909 }
1910 }
1911
1912 None
1913 }
1914
1915 pub fn object_value(&self) -> Option<CstObject> {
1917 self.value()?.as_object()
1918 }
1919
1920 pub fn object_value_or_set(&self) -> CstObject {
1922 match self.value() {
1923 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1924 _ => {
1925 self.set_value(CstInputValue::Object(Vec::new()));
1926 self.object_value().unwrap()
1927 }
1928 }
1929 }
1930
1931 pub fn array_value(&self) -> Option<CstArray> {
1933 self.value()?.as_array()
1934 }
1935
1936 pub fn array_value_or_set(&self) -> CstArray {
1938 match self.value() {
1939 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1940 _ => {
1941 self.set_value(CstInputValue::Array(Vec::new()));
1942 self.array_value().unwrap()
1943 }
1944 }
1945 }
1946
1947 pub fn previous_property(&self) -> Option<CstObjectProp> {
1949 for sibling in self.previous_siblings() {
1950 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1951 return Some(prop);
1952 }
1953 }
1954 None
1955 }
1956
1957 pub fn next_property(&self) -> Option<CstObjectProp> {
1959 for sibling in self.next_siblings() {
1960 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1961 return Some(prop);
1962 }
1963 }
1964 None
1965 }
1966
1967 pub fn replace_with(self, key: &str, replacement: CstInputValue) -> Option<CstNode> {
1969 replace_with(self.into(), InsertValue::Property(key, replacement))
1970 }
1971
1972 pub fn remove(self) {
1974 remove_comma_separated(self.into())
1975 }
1976
1977 #[cfg(feature = "serde")]
1981 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1982 self.value()?.to_serde_value()
1983 }
1984
1985 #[cfg(feature = "serde")]
1986 fn name_decoded(&self) -> Option<String> {
1987 match self.name()? {
1988 ObjectPropName::String(s) => s.decoded_value().ok(),
1989 ObjectPropName::Word(w) => Some(w.0.borrow().value.clone()),
1990 }
1991 }
1992}
1993
1994impl Display for CstObjectProp {
1995 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1996 for child in &self.0.borrow().value {
1997 write!(f, "{}", child)?;
1998 }
1999 Ok(())
2000 }
2001}
2002
2003#[derive(Debug, Clone)]
2005pub enum ObjectPropName {
2006 String(CstStringLit),
2007 Word(CstWordLit),
2008}
2009
2010impl ObjectPropName {
2011 add_root_node_method!();
2012 add_parent_info_methods!();
2013
2014 pub fn as_string_lit(&self) -> Option<CstStringLit> {
2016 match self {
2017 ObjectPropName::String(n) => Some(n.clone()),
2018 ObjectPropName::Word(_) => None,
2019 }
2020 }
2021
2022 pub fn as_word_lit(&self) -> Option<CstWordLit> {
2024 match self {
2025 ObjectPropName::String(_) => None,
2026 ObjectPropName::Word(n) => Some(n.clone()),
2027 }
2028 }
2029
2030 pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
2032 match self {
2033 ObjectPropName::String(n) => n.decoded_value(),
2034 ObjectPropName::Word(n) => Ok(n.0.borrow().value.clone()),
2035 }
2036 }
2037
2038 fn parent_info(&self) -> Option<ParentInfo> {
2039 match self {
2040 ObjectPropName::String(n) => n.parent_info(),
2041 ObjectPropName::Word(n) => n.parent_info(),
2042 }
2043 }
2044}
2045
2046impl From<ObjectPropName> for CstNode {
2047 fn from(value: ObjectPropName) -> Self {
2048 match value {
2049 ObjectPropName::String(n) => n.into(),
2050 ObjectPropName::Word(n) => n.into(),
2051 }
2052 }
2053}
2054
2055type CstArrayInner = RefCell<CstChildrenInner>;
2056
2057#[derive(Debug, Clone)]
2059pub struct CstArray(Rc<CstArrayInner>);
2060
2061impl_container_methods!(CstArray, Array);
2062
2063impl CstArray {
2064 add_root_node_method!();
2065
2066 fn new_no_tokens() -> Self {
2067 Self(CstValueInner::new(Vec::new()))
2068 }
2069
2070 fn new_with_tokens() -> Self {
2071 let array = CstArray::new_no_tokens();
2072 let container: CstContainerNode = array.clone().into();
2073 container.raw_append_children(vec![CstToken::new('[').into(), CstToken::new(']').into()]);
2074 array
2075 }
2076
2077 pub fn elements(&self) -> Vec<CstNode> {
2079 self
2080 .0
2081 .borrow()
2082 .value
2083 .iter()
2084 .filter(|child| match child {
2085 CstNode::Container(_) => true,
2086 CstNode::Leaf(leaf) => match leaf {
2087 CstLeafNode::BooleanLit(_)
2088 | CstLeafNode::NullKeyword(_)
2089 | CstLeafNode::NumberLit(_)
2090 | CstLeafNode::StringLit(_)
2091 | CstLeafNode::WordLit(_) => true,
2092 CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
2093 false
2094 }
2095 },
2096 })
2097 .cloned()
2098 .collect()
2099 }
2100
2101 pub fn append(&self, value: CstInputValue) -> CstNode {
2105 self.insert_or_append(None, value)
2106 }
2107
2108 pub fn insert(&self, index: usize, value: CstInputValue) -> CstNode {
2112 self.insert_or_append(Some(index), value)
2113 }
2114
2115 pub fn ensure_multiline(&self) {
2117 ensure_multiline(&self.clone().into());
2118 }
2119
2120 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
2122 set_trailing_commas(mode, &self.clone().into(), self.elements().into_iter());
2123 }
2124
2125 fn insert_or_append(&self, index: Option<usize>, value: CstInputValue) -> CstNode {
2126 insert_or_append_to_container(
2127 &CstContainerNode::Array(self.clone()),
2128 self.elements(),
2129 index,
2130 InsertValue::Value(value),
2131 )
2132 }
2133
2134 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
2136 replace_with(self.into(), InsertValue::Value(replacement))
2137 }
2138
2139 pub fn remove(self) {
2141 remove_comma_separated(self.into())
2142 }
2143
2144 #[cfg(feature = "serde")]
2146 pub fn to_serde_value(&self) -> Option<serde_json::Value> {
2147 let elements: Vec<serde_json::Value> = self
2148 .elements()
2149 .into_iter()
2150 .filter_map(|element| element.to_serde_value())
2151 .collect();
2152 Some(serde_json::Value::Array(elements))
2153 }
2154}
2155
2156impl Display for CstArray {
2157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2158 for child in &self.0.borrow().value {
2159 write!(f, "{}", child)?;
2160 }
2161 Ok(())
2162 }
2163}
2164
2165#[derive(Debug, Clone)]
2167pub struct CstToken(Rc<RefCell<CstValueInner<char>>>);
2168
2169impl_leaf_methods!(CstToken, Token);
2170
2171impl CstToken {
2172 fn new(value: char) -> Self {
2173 Self(CstValueInner::new(value))
2174 }
2175
2176 pub fn set_value(&self, value: char) {
2178 self.0.borrow_mut().value = value;
2179 }
2180
2181 pub fn value(&self) -> char {
2183 self.0.borrow().value
2184 }
2185
2186 pub fn remove(self) {
2188 Into::<CstNode>::into(self).remove_raw()
2189 }
2190}
2191
2192impl Display for CstToken {
2193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2194 write!(f, "{}", self.0.borrow().value)
2195 }
2196}
2197
2198#[derive(Debug, Clone)]
2200pub struct CstWhitespace(Rc<RefCell<CstValueInner<String>>>);
2201
2202impl_leaf_methods!(CstWhitespace, Whitespace);
2203
2204impl CstWhitespace {
2205 fn new(value: String) -> Self {
2206 Self(CstValueInner::new(value))
2207 }
2208
2209 pub fn set_value(&self, value: String) {
2211 self.0.borrow_mut().value = value;
2212 }
2213
2214 pub fn value(&self) -> String {
2216 self.0.borrow().value.clone()
2217 }
2218
2219 pub fn remove(self) {
2221 Into::<CstNode>::into(self).remove_raw()
2222 }
2223}
2224
2225impl Display for CstWhitespace {
2226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2227 write!(f, "{}", self.0.borrow().value)
2228 }
2229}
2230
2231#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
2233pub enum CstNewlineKind {
2234 #[default]
2235 LineFeed,
2236 CarriageReturnLineFeed,
2237}
2238
2239#[derive(Debug, Clone)]
2241pub struct CstNewline(Rc<RefCell<CstValueInner<CstNewlineKind>>>);
2242
2243impl_leaf_methods!(CstNewline, Newline);
2244
2245impl CstNewline {
2246 fn new(kind: CstNewlineKind) -> Self {
2247 Self(CstValueInner::new(kind))
2248 }
2249
2250 pub fn kind(&self) -> CstNewlineKind {
2252 self.0.borrow().value
2253 }
2254
2255 pub fn set_kind(&self, kind: CstNewlineKind) {
2257 self.0.borrow_mut().value = kind;
2258 }
2259
2260 pub fn remove(self) {
2262 Into::<CstNode>::into(self).remove_raw()
2263 }
2264}
2265
2266impl Display for CstNewline {
2267 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2268 match self.0.borrow().value {
2269 #[allow(clippy::write_with_newline)] CstNewlineKind::LineFeed => write!(f, "\n"),
2271 CstNewlineKind::CarriageReturnLineFeed => write!(f, "\r\n"),
2272 }
2273 }
2274}
2275
2276#[derive(Debug, Clone)]
2277pub struct CstComment(Rc<RefCell<CstValueInner<String>>>);
2278
2279impl_leaf_methods!(CstComment, Comment);
2280
2281impl CstComment {
2282 fn new(value: String) -> Self {
2283 Self(CstValueInner::new(value))
2284 }
2285
2286 pub fn is_line_comment(&self) -> bool {
2288 self.0.borrow().value.starts_with("//")
2289 }
2290
2291 pub fn set_raw_value(&self, value: String) {
2296 self.0.borrow_mut().value = value;
2297 }
2298
2299 pub fn raw_value(&self) -> String {
2301 self.0.borrow().value.clone()
2302 }
2303
2304 pub fn remove(self) {
2306 if self.is_line_comment() {
2307 for node in self.previous_siblings() {
2308 if node.is_whitespace() {
2309 node.remove_raw();
2310 } else {
2311 if node.is_newline() {
2312 node.remove_raw();
2313 }
2314 break;
2315 }
2316 }
2317 }
2318
2319 Into::<CstNode>::into(self).remove_raw()
2320 }
2321}
2322
2323impl Display for CstComment {
2324 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2325 write!(f, "{}", self.0.borrow().value)
2326 }
2327}
2328
2329struct CstBuilder<'a> {
2330 pub text: &'a str,
2331 pub tokens: VecDeque<crate::tokens::TokenAndRange<'a>>,
2332}
2333
2334impl<'a> CstBuilder<'a> {
2335 pub fn build(&mut self, ast_value: Option<crate::ast::Value<'a>>) -> CstRootNode {
2336 let root_node = CstContainerNode::Root(CstRootNode(Rc::new(RefCell::new(CstChildrenInner {
2337 parent: None,
2338 value: Vec::new(),
2339 }))));
2340
2341 if let Some(ast_value) = ast_value {
2342 let range = ast_value.range();
2343 self.scan_from_to(&root_node, 0, range.start);
2344 self.build_value(&root_node, ast_value);
2345 self.scan_from_to(&root_node, range.end, self.text.len());
2346 } else {
2347 self.scan_from_to(&root_node, 0, self.text.len());
2348 }
2349
2350 match root_node {
2351 CstContainerNode::Root(node) => node,
2352 _ => unreachable!(),
2353 }
2354 }
2355
2356 fn scan_from_to(&mut self, container: &CstContainerNode, from: usize, to: usize) {
2357 if from == to {
2358 return;
2359 }
2360
2361 let mut last_from = from;
2362 while let Some(token) = self.tokens.front() {
2363 if token.range.end <= from {
2364 self.tokens.pop_front();
2365 } else if token.range.start < to {
2366 if token.range.start > last_from {
2367 self.build_whitespace(container, &self.text[last_from..token.range.start]);
2368 }
2369 let token = self.tokens.pop_front().unwrap();
2370 match token.token {
2371 crate::tokens::Token::OpenBrace
2372 | crate::tokens::Token::CloseBrace
2373 | crate::tokens::Token::OpenBracket
2374 | crate::tokens::Token::CloseBracket
2375 | crate::tokens::Token::Comma
2376 | crate::tokens::Token::Colon => {
2377 self.build_token(container, token.token.as_str().chars().next().unwrap());
2378 }
2379 crate::tokens::Token::Null
2380 | crate::tokens::Token::String(_)
2381 | crate::tokens::Token::Word(_)
2382 | crate::tokens::Token::Boolean(_)
2383 | crate::tokens::Token::Number(_) => unreachable!(
2384 "programming error parsing cst {:?} scanning {} to {}",
2385 token.token, from, to
2386 ),
2387 crate::tokens::Token::CommentLine(_) | crate::tokens::Token::CommentBlock(_) => {
2388 container
2389 .raw_append_child(CstComment::new(self.text[token.range.start..token.range.end].to_string()).into());
2390 }
2391 }
2392 last_from = token.range.end;
2393 } else {
2394 break;
2395 }
2396 }
2397
2398 if last_from < to {
2399 self.build_whitespace(container, &self.text[last_from..to]);
2400 }
2401 }
2402
2403 fn build_value(&mut self, container: &CstContainerNode, ast_value: ast::Value<'_>) {
2404 match ast_value {
2405 ast::Value::StringLit(string_lit) => self.build_string_lit(container, string_lit),
2406 ast::Value::NumberLit(number_lit) => {
2407 container.raw_append_child(CstNumberLit::new(number_lit.value.to_string()).into())
2408 }
2409 ast::Value::BooleanLit(boolean_lit) => container.raw_append_child(CstBooleanLit::new(boolean_lit.value).into()),
2410 ast::Value::Object(object) => {
2411 let object = self.build_object(object);
2412 container.raw_append_child(object.into())
2413 }
2414 ast::Value::Array(array) => {
2415 let array = self.build_array(array);
2416 container.raw_append_child(array.into())
2417 }
2418 ast::Value::NullKeyword(_) => container.raw_append_child(CstNullKeyword::new().into()),
2419 }
2420 }
2421
2422 fn build_object(&mut self, object: ast::Object<'_>) -> CstContainerNode {
2423 let container = CstContainerNode::Object(CstObject::new_no_tokens());
2424 let mut last_range_end = object.range.start;
2425 for prop in object.properties {
2426 self.scan_from_to(&container, last_range_end, prop.range.start);
2427 last_range_end = prop.range.end;
2428 let object_prop = self.build_object_prop(prop);
2429 container.raw_append_child(CstNode::Container(object_prop));
2430 }
2431 self.scan_from_to(&container, last_range_end, object.range.end);
2432
2433 container
2434 }
2435
2436 fn build_object_prop(&mut self, prop: ast::ObjectProp<'_>) -> CstContainerNode {
2437 let container = CstContainerNode::ObjectProp(CstObjectProp::new());
2438 let name_range = prop.name.range();
2439 let value_range = prop.value.range();
2440
2441 match prop.name {
2442 ast::ObjectPropName::String(string_lit) => {
2443 self.build_string_lit(&container, string_lit);
2444 }
2445 ast::ObjectPropName::Word(word_lit) => {
2446 container.raw_append_child(CstWordLit::new(word_lit.value.to_string()).into());
2447 }
2448 }
2449
2450 self.scan_from_to(&container, name_range.end, value_range.start);
2451 self.build_value(&container, prop.value);
2452
2453 container
2454 }
2455
2456 fn build_token(&self, container: &CstContainerNode, value: char) {
2457 container.raw_append_child(CstToken::new(value).into());
2458 }
2459
2460 fn build_whitespace(&self, container: &CstContainerNode, value: &str) {
2461 if value.is_empty() {
2462 return;
2463 }
2464
2465 let mut last_found_index = 0;
2466 let mut chars = value.char_indices().peekable();
2467 let maybe_add_previous_text = |from: usize, to: usize| {
2468 let text = &value[from..to];
2469 if !text.is_empty() {
2470 container.raw_append_child(CstWhitespace::new(text.to_string()).into());
2471 }
2472 };
2473 while let Some((i, c)) = chars.next() {
2474 if c == '\r' && chars.peek().map(|(_, c)| *c) == Some('\n') {
2475 maybe_add_previous_text(last_found_index, i);
2476 container.raw_append_child(CstNewline::new(CstNewlineKind::CarriageReturnLineFeed).into());
2477 last_found_index = i + 2;
2478 chars.next(); } else if c == '\n' {
2480 maybe_add_previous_text(last_found_index, i);
2481 container.raw_append_child(CstNewline::new(CstNewlineKind::LineFeed).into());
2482 last_found_index = i + 1;
2483 }
2484 }
2485
2486 maybe_add_previous_text(last_found_index, value.len());
2487 }
2488
2489 fn build_string_lit(&self, container: &CstContainerNode, lit: ast::StringLit<'_>) {
2490 container.raw_append_child(CstStringLit::new(self.text[lit.range.start..lit.range.end].to_string()).into());
2491 }
2492
2493 fn build_array(&mut self, array: ast::Array<'_>) -> CstContainerNode {
2494 let container = CstContainerNode::Array(CstArray::new_no_tokens());
2495 let mut last_range_end = array.range.start;
2496 for element in array.elements {
2497 let element_range = element.range();
2498 self.scan_from_to(&container, last_range_end, element_range.start);
2499 self.build_value(&container, element);
2500 last_range_end = element_range.end;
2501 }
2502 self.scan_from_to(&container, last_range_end, array.range.end);
2503
2504 container
2505 }
2506}
2507
2508fn remove_comma_separated(node: CstNode) {
2509 fn check_next_node_same_line(trailing_comma: &CstToken) -> bool {
2510 for sibling in trailing_comma.next_siblings() {
2511 match sibling {
2512 CstNode::Container(_) => return true,
2513 CstNode::Leaf(n) => match n {
2514 CstLeafNode::BooleanLit(_)
2515 | CstLeafNode::NullKeyword(_)
2516 | CstLeafNode::NumberLit(_)
2517 | CstLeafNode::StringLit(_)
2518 | CstLeafNode::WordLit(_)
2519 | CstLeafNode::Token(_) => return true,
2520 CstLeafNode::Whitespace(_) | CstLeafNode::Comment(_) => {
2521 }
2523 CstLeafNode::Newline(_) => return false,
2524 },
2525 }
2526 }
2527
2528 true
2529 }
2530
2531 let parent = node.parent();
2532 let trailing_comma = node.trailing_comma();
2533 let is_in_array_or_obj = parent
2534 .as_ref()
2535 .map(|p| matches!(p, CstContainerNode::Array(_) | CstContainerNode::Object(_)))
2536 .unwrap_or(false);
2537 let remove_up_to_next_line = trailing_comma
2538 .as_ref()
2539 .map(|c| !check_next_node_same_line(c))
2540 .unwrap_or(true);
2541
2542 for previous in node.previous_siblings() {
2543 if previous.is_trivia() && !previous.is_newline() {
2544 previous.remove_raw();
2545 } else {
2546 break;
2547 }
2548 }
2549
2550 let mut found_newline = false;
2551
2552 if trailing_comma.is_some() {
2554 let mut next_siblings = node.next_siblings();
2555 for next in next_siblings.by_ref() {
2556 let is_comma = next.is_comma();
2557 if next.is_newline() {
2558 found_newline = true;
2559 }
2560 next.remove_raw();
2561 if is_comma {
2562 break;
2563 }
2564 }
2565 } else if is_in_array_or_obj && let Some(previous_comma) = node.previous_siblings().find(|n| n.is_comma()) {
2566 previous_comma.remove();
2567 }
2568
2569 if remove_up_to_next_line && !found_newline {
2571 let mut next_siblings = node.next_siblings().peekable();
2572 while let Some(sibling) = next_siblings.next() {
2573 if sibling.is_trivia() {
2574 if sibling.is_newline() {
2575 sibling.remove_raw();
2576 break;
2577 } else if sibling.is_whitespace()
2578 && next_siblings
2579 .peek()
2580 .map(|n| !n.is_whitespace() && !n.is_newline() && !n.is_comment())
2581 .unwrap_or(false)
2582 {
2583 break;
2584 }
2585 sibling.remove_raw();
2586 } else {
2587 break;
2588 }
2589 }
2590 }
2591
2592 node.remove_raw();
2593
2594 if let Some(parent) = parent {
2595 match parent {
2596 CstContainerNode::Root(n) => {
2597 if n.children().iter().all(|c| c.is_whitespace() || c.is_newline()) {
2598 n.clear_children();
2599 }
2600 }
2601 CstContainerNode::Object(_) | CstContainerNode::Array(_) => {
2602 let children = parent.children();
2603 if children
2604 .iter()
2605 .skip(1)
2606 .take(children.len() - 2)
2607 .all(|c| c.is_whitespace() || c.is_newline())
2608 {
2609 for c in children {
2610 if c.is_whitespace() || c.is_newline() {
2611 c.remove();
2612 }
2613 }
2614 }
2615 }
2616 CstContainerNode::ObjectProp(_) => {}
2617 }
2618 }
2619}
2620
2621fn indent_text(node: &CstNode) -> Option<String> {
2622 let mut last_whitespace: Option<String> = None;
2623 for previous_sibling in node.previous_siblings() {
2624 match previous_sibling {
2625 CstNode::Container(_) => return None,
2626 CstNode::Leaf(leaf) => match leaf {
2627 CstLeafNode::Newline(_) => {
2628 return last_whitespace;
2629 }
2630 CstLeafNode::Whitespace(whitespace) => {
2631 last_whitespace = match last_whitespace {
2632 Some(last_whitespace) => Some(format!("{}{}", whitespace.value(), last_whitespace)),
2633 None => Some(whitespace.value()),
2634 };
2635 }
2636 CstLeafNode::Comment(_) => {
2637 last_whitespace = None;
2638 }
2639 _ => return None,
2640 },
2641 }
2642 }
2643 last_whitespace
2644}
2645
2646fn uses_trailing_commas(node: CstNode) -> bool {
2647 let node = match node {
2648 CstNode::Container(node) => node,
2649 CstNode::Leaf(_) => return false,
2650 };
2651 let mut pending_nodes: VecDeque<CstContainerNode> = VecDeque::from([node.clone()]);
2652 while let Some(node) = pending_nodes.pop_front() {
2653 let children = node.children();
2654 if !node.is_root() {
2655 if let Some(object) = node.as_object() {
2656 if children.iter().any(|c| c.is_whitespace()) {
2657 let properties = object.properties();
2658 if let Some(last_property) = properties.last() {
2659 return last_property.trailing_comma().is_some();
2660 }
2661 }
2662 } else if let Some(object) = node.as_array()
2663 && children.iter().any(|c| c.is_whitespace())
2664 {
2665 let elements = object.elements();
2666 if let Some(last_property) = elements.last() {
2667 return last_property.trailing_comma().is_some();
2668 }
2669 }
2670 }
2671
2672 for child in children {
2673 if let CstNode::Container(child) = child {
2674 pending_nodes.push_back(child);
2675 }
2676 }
2677 }
2678
2679 false }
2681
2682fn replace_with(node: CstNode, replacement: InsertValue) -> Option<CstNode> {
2683 let mut child_index = node.child_index();
2684 let parent = node.parent()?;
2685 let indents = compute_indents(&parent.clone().into());
2686 let style_info = StyleInfo {
2687 newline_kind: parent.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2688 uses_trailing_commas: uses_trailing_commas(parent.clone().into()),
2689 };
2690 parent.remove_child_set_no_parent(child_index);
2691 parent.raw_insert_value_with_internal_indent(Some(&mut child_index), replacement, &style_info, &indents);
2692 parent.child_at_index(child_index - 1)
2693}
2694
2695enum InsertValue<'a> {
2696 Value(CstInputValue),
2697 Property(&'a str, CstInputValue),
2698}
2699
2700fn insert_or_append_to_container(
2701 container: &CstContainerNode,
2702 elements: Vec<CstNode>,
2703 index: Option<usize>,
2704 value: InsertValue,
2705) -> CstNode {
2706 fn has_separating_newline(siblings: impl Iterator<Item = CstNode>) -> bool {
2707 for sibling in siblings {
2708 if sibling.is_newline() {
2709 return true;
2710 } else if sibling.is_trivia() {
2711 continue;
2712 } else {
2713 break;
2714 }
2715 }
2716 false
2717 }
2718
2719 trim_inner_start_and_end_blanklines(container);
2720
2721 let children = container.children();
2722 let index = index.unwrap_or(elements.len());
2723 let index = std::cmp::min(index, elements.len());
2724 let next_node = elements.get(index);
2725 let previous_node = if index == 0 { None } else { elements.get(index - 1) };
2726 let style_info = StyleInfo {
2727 newline_kind: container.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2728 uses_trailing_commas: uses_trailing_commas(container.clone().into()),
2729 };
2730 let indents = compute_indents(&container.clone().into());
2731 let child_indents = elements
2732 .first()
2733 .map(compute_indents)
2734 .unwrap_or_else(|| indents.indent());
2735 let has_newline = children.iter().any(|child| child.is_newline());
2736 let force_multiline = has_newline
2737 || match &value {
2738 InsertValue::Value(v) => v.force_multiline(),
2739 InsertValue::Property(..) => true,
2740 };
2741 let mut insert_index: usize;
2742 let inserted_node: CstNode;
2743 if let Some(previous_node) = previous_node {
2744 if previous_node.trailing_comma().is_none() {
2745 let mut index = previous_node.child_index() + 1;
2746 container.raw_insert_child(Some(&mut index), CstToken::new(',').into());
2747 }
2748
2749 let trailing_comma: CstNode = previous_node.trailing_comma().unwrap().into();
2750 insert_index = trailing_comma
2751 .trailing_comments_same_line()
2752 .last()
2753 .map(|t| t.child_index())
2754 .unwrap_or_else(|| trailing_comma.child_index())
2755 + 1;
2756 if force_multiline {
2757 container.raw_insert_children(
2758 Some(&mut insert_index),
2759 vec![
2760 CstNewline::new(style_info.newline_kind).into(),
2761 CstStringLit::new(child_indents.current_indent.clone()).into(),
2762 ],
2763 );
2764 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2765 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2766 } else {
2767 container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2768 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2769 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2770 }
2771 } else {
2772 insert_index = if elements.is_empty() {
2773 children
2774 .iter()
2775 .rev()
2776 .skip(1)
2777 .take_while(|t| t.is_whitespace() || t.is_newline())
2778 .last()
2779 .unwrap_or_else(|| children.last().unwrap())
2780 .child_index()
2781 } else {
2782 children.first().unwrap().child_index() + 1
2783 };
2784 if force_multiline {
2785 container.raw_insert_children(
2786 Some(&mut insert_index),
2787 vec![
2788 CstNewline::new(style_info.newline_kind).into(),
2789 CstStringLit::new(child_indents.current_indent.clone()).into(),
2790 ],
2791 );
2792 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2793 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2794 if next_node.is_none()
2795 && !has_separating_newline(container.child_at_index(insert_index - 1).unwrap().next_siblings())
2796 {
2797 container.raw_insert_children(
2798 Some(&mut insert_index),
2799 vec![
2800 CstNewline::new(style_info.newline_kind).into(),
2801 CstStringLit::new(indents.current_indent.clone()).into(),
2802 ],
2803 );
2804 }
2805 } else {
2806 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2807 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2808 }
2809 }
2810
2811 if next_node.is_some() {
2812 container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2813
2814 if force_multiline {
2815 let comma_token = container.child_at_index(insert_index - 1).unwrap();
2816 if !has_separating_newline(comma_token.next_siblings()) {
2817 container.raw_insert_children(
2818 Some(&mut insert_index),
2819 vec![
2820 CstNewline::new(style_info.newline_kind).into(),
2821 CstStringLit::new(indents.current_indent.clone()).into(),
2822 ],
2823 );
2824 }
2825 } else {
2826 container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2827 }
2828 } else if style_info.uses_trailing_commas && force_multiline {
2829 container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2830 }
2831
2832 inserted_node
2833}
2834
2835fn set_trailing_commas(
2836 mode: TrailingCommaMode,
2837 parent: &CstContainerNode,
2838 elems_or_props: impl Iterator<Item = CstNode>,
2839) {
2840 let mut elems_or_props = elems_or_props.peekable();
2841 let use_trailing_commas = match mode {
2842 TrailingCommaMode::Never => false,
2843 TrailingCommaMode::IfMultiline => true,
2844 };
2845 while let Some(element) = elems_or_props.next() {
2846 if elems_or_props.peek().is_none() {
2848 if use_trailing_commas {
2849 if element.trailing_comma().is_none() && parent.children().iter().any(|c| c.is_newline()) {
2850 let mut insert_index = element.child_index() + 1;
2851 parent.raw_insert_child(Some(&mut insert_index), CstToken::new(',').into());
2852 }
2853 } else if let Some(trailing_comma) = element.trailing_comma() {
2854 trailing_comma.remove();
2855 }
2856 }
2857
2858 let maybe_prop_value = element.as_object_prop().and_then(|p| p.value());
2860 match maybe_prop_value.unwrap_or(element) {
2861 CstNode::Container(CstContainerNode::Array(array)) => {
2862 array.set_trailing_commas(mode);
2863 }
2864 CstNode::Container(CstContainerNode::Object(object)) => {
2865 object.set_trailing_commas(mode);
2866 }
2867 _ => {}
2868 }
2869 }
2870}
2871
2872fn trim_inner_start_and_end_blanklines(node: &CstContainerNode) {
2873 fn remove_blank_lines_after_first(children: &mut Peekable<impl Iterator<Item = CstNode>>) {
2874 for child in children.by_ref() {
2876 if child.is_whitespace() {
2877 } else if child.is_newline() {
2879 break; } else {
2881 return; }
2883 }
2884
2885 let mut pending = Vec::new();
2886 for child in children.by_ref() {
2887 if child.is_whitespace() {
2888 pending.push(child);
2889 } else if child.is_newline() {
2890 child.remove();
2891 for child in pending.drain(..) {
2892 child.remove();
2893 }
2894 } else {
2895 break;
2896 }
2897 }
2898 }
2899
2900 let children = node.children();
2901 let len = children.len();
2902
2903 if len < 2 {
2904 return; }
2906
2907 let mut children = children.into_iter().skip(1).take(len - 2).peekable();
2909 remove_blank_lines_after_first(&mut children);
2910 let mut children = children.rev().peekable();
2911 remove_blank_lines_after_first(&mut children);
2912}
2913
2914fn ensure_multiline(container: &CstContainerNode) {
2915 let children = container.children();
2916 if children.iter().any(|c| c.is_newline()) {
2917 return;
2918 }
2919
2920 let indents = compute_indents(&container.clone().into());
2921 let child_indents = indents.indent();
2922 let newline_kind = container
2923 .root_node()
2924 .map(|r| r.newline_kind())
2925 .unwrap_or(CstNewlineKind::LineFeed);
2926
2927 let children_len = children.len();
2929 let mut children = children.into_iter().skip(1).peekable().take(children_len - 2);
2930 let mut index = 1;
2931 while let Some(child) = children.next() {
2932 if child.is_whitespace() {
2933 child.remove();
2934 continue;
2935 } else {
2936 container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2938 container.raw_insert_child(
2939 Some(&mut index),
2940 CstWhitespace::new(child_indents.current_indent.clone()).into(),
2941 );
2942
2943 index += 1;
2945
2946 let mut trailing_whitespace = Vec::new();
2948 for next_child in children.by_ref() {
2949 if next_child.is_whitespace() {
2950 trailing_whitespace.push(next_child);
2951 } else {
2952 index += 1 + trailing_whitespace.len();
2953 trailing_whitespace.clear();
2954 if next_child.token_char() == Some(',') {
2955 break;
2956 }
2957 }
2958 }
2959
2960 for trailing_whitespace in trailing_whitespace {
2961 trailing_whitespace.remove();
2962 }
2963 }
2964 }
2965
2966 container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2968 if !indents.current_indent.is_empty() {
2969 container.raw_insert_child(Some(&mut index), CstWhitespace::new(indents.current_indent).into());
2970 }
2971}
2972
2973#[derive(Debug)]
2974struct Indents {
2975 current_indent: String,
2976 single_indent: String,
2977}
2978
2979impl Indents {
2980 pub fn indent(&self) -> Indents {
2981 Indents {
2982 current_indent: format!("{}{}", self.current_indent, self.single_indent),
2983 single_indent: self.single_indent.clone(),
2984 }
2985 }
2986}
2987
2988fn compute_indents(node: &CstNode) -> Indents {
2989 let mut indent_level = 0;
2990 let mut stored_last_indent = node.indent_text();
2991 let mut ancestors = node.ancestors().peekable();
2992
2993 while ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
2994 ancestors.next();
2995 }
2996
2997 while let Some(ancestor) = ancestors.next() {
2998 if ancestor.is_root() {
2999 break;
3000 }
3001
3002 if ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
3003 continue;
3004 }
3005
3006 indent_level += 1;
3007
3008 if let Some(indent_text) = ancestor.indent_text() {
3009 match stored_last_indent {
3010 Some(last_indent) => {
3011 if let Some(single_indent_text) = last_indent.strip_prefix(&indent_text) {
3012 return Indents {
3013 current_indent: format!("{}{}", last_indent, single_indent_text.repeat(indent_level - 1)),
3014 single_indent: single_indent_text.to_string(),
3015 };
3016 }
3017 stored_last_indent = None;
3018 }
3019 None => {
3020 stored_last_indent = Some(indent_text);
3021 }
3022 }
3023 } else {
3024 stored_last_indent = None;
3025 }
3026 }
3027
3028 if indent_level == 1
3029 && let Some(indent_text) = node.indent_text()
3030 {
3031 return Indents {
3032 current_indent: indent_text.clone(),
3033 single_indent: indent_text,
3034 };
3035 }
3036
3037 if let Some(root_value) = node.root_node().and_then(|r| r.value()) {
3039 for child in root_value.children() {
3040 if let Some(single_indent) = child.indent_text() {
3041 return Indents {
3042 current_indent: single_indent.repeat(indent_level),
3043 single_indent,
3044 };
3045 }
3046 }
3047 }
3048
3049 let single_indent = " ";
3051 Indents {
3052 current_indent: single_indent.repeat(indent_level),
3053 single_indent: single_indent.to_string(),
3054 }
3055}
3056
3057struct AncestorIterator {
3058 next: Option<CstContainerNode>,
3061}
3062
3063impl AncestorIterator {
3064 pub fn new(node: CstNode) -> Self {
3065 Self {
3066 next: node.parent_info().map(|i| i.parent.as_container_node()),
3067 }
3068 }
3069}
3070
3071impl Iterator for AncestorIterator {
3072 type Item = CstContainerNode;
3073
3074 fn next(&mut self) -> Option<Self::Item> {
3075 let next = self.next.take()?;
3076 self.next = next.parent_info().map(|i| i.parent.as_container_node());
3077 Some(next)
3078 }
3079}
3080
3081struct NextSiblingIterator {
3082 next: Option<CstNode>,
3085}
3086
3087impl NextSiblingIterator {
3088 pub fn new(node: CstNode) -> Self {
3089 Self {
3090 next: node.next_sibling(),
3091 }
3092 }
3093}
3094
3095impl Iterator for NextSiblingIterator {
3096 type Item = CstNode;
3097
3098 fn next(&mut self) -> Option<Self::Item> {
3099 let next_sibling = self.next.take()?;
3100 self.next = next_sibling.next_sibling();
3101 Some(next_sibling)
3102 }
3103}
3104
3105struct PreviousSiblingIterator {
3106 previous: Option<CstNode>,
3109}
3110
3111impl PreviousSiblingIterator {
3112 pub fn new(node: CstNode) -> Self {
3113 Self {
3114 previous: node.previous_sibling(),
3115 }
3116 }
3117}
3118
3119impl Iterator for PreviousSiblingIterator {
3120 type Item = CstNode;
3121
3122 fn next(&mut self) -> Option<Self::Item> {
3123 let previous_sibling = self.previous.take()?;
3124 self.previous = previous_sibling.previous_sibling();
3125 Some(previous_sibling)
3126 }
3127}
3128
3129#[cfg(test)]
3130mod test {
3131 use pretty_assertions::assert_eq;
3132
3133 use crate::cst::CstInputValue;
3134 use crate::cst::TrailingCommaMode;
3135 use crate::json;
3136
3137 use super::CstRootNode;
3138
3139 #[test]
3140 fn single_indent_text() {
3141 let cases = [
3142 (
3143 " ",
3144 r#"
3145{
3146 "prop": {
3147 "nested": 4
3148 }
3149}
3150 "#,
3151 ),
3152 (
3153 " ",
3154 r#"
3155{
3156 /* test */ "prop": {}
3157}
3158 "#,
3159 ),
3160 (
3161 " ",
3162 r#"
3163{
3164 /* test */ "prop": {}
3165}
3166 "#,
3167 ),
3168 (
3169 "\t",
3170 "
3171{
3172\t/* test */ \"prop\": {}
3173}
3174 ",
3175 ),
3176 ];
3177 for (expected, text) in cases {
3178 let root = build_cst(text);
3179 assert_eq!(root.single_indent_text(), Some(expected.to_string()), "Text: {}", text);
3180 }
3181 }
3182
3183 #[test]
3184 fn modify_values() {
3185 let cst = build_cst(
3186 r#"{
3187 "value": 5,
3188 // comment
3189 "value2": "hello",
3190 value3: true
3191}"#,
3192 );
3193
3194 let root_value = cst.value().unwrap();
3195 let root_obj = root_value.as_object().unwrap();
3196 {
3197 let prop = root_obj.get("value").unwrap();
3198 prop
3199 .value()
3200 .unwrap()
3201 .as_number_lit()
3202 .unwrap()
3203 .set_raw_value("10".to_string());
3204 assert!(prop.trailing_comma().is_some());
3205 assert!(prop.previous_property().is_none());
3206 assert_eq!(
3207 prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3208 "value2"
3209 );
3210 assert_eq!(prop.indent_text().unwrap(), " ");
3211 }
3212 {
3213 let prop = root_obj.get("value2").unwrap();
3214 prop
3215 .value()
3216 .unwrap()
3217 .as_string_lit()
3218 .unwrap()
3219 .set_raw_value("\"5\"".to_string());
3220 assert!(prop.trailing_comma().is_some());
3221 assert_eq!(
3222 prop
3223 .previous_property()
3224 .unwrap()
3225 .name()
3226 .unwrap()
3227 .decoded_value()
3228 .unwrap(),
3229 "value"
3230 );
3231 assert_eq!(
3232 prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3233 "value3"
3234 );
3235 }
3236 {
3237 let prop = root_obj.get("value3").unwrap();
3238 prop.value().unwrap().as_boolean_lit().unwrap().set_value(false);
3239 prop
3240 .name()
3241 .unwrap()
3242 .as_word_lit()
3243 .unwrap()
3244 .set_raw_value("value4".to_string());
3245 assert!(prop.trailing_comma().is_none());
3246 assert_eq!(
3247 prop
3248 .previous_property()
3249 .unwrap()
3250 .name()
3251 .unwrap()
3252 .decoded_value()
3253 .unwrap(),
3254 "value2"
3255 );
3256 assert!(prop.next_property().is_none());
3257 }
3258
3259 assert_eq!(
3260 cst.to_string(),
3261 r#"{
3262 "value": 10,
3263 // comment
3264 "value2": "5",
3265 value4: false
3266}"#
3267 );
3268 }
3269
3270 #[test]
3271 fn remove_properties() {
3272 fn run_test(prop_name: &str, json: &str, expected: &str) {
3273 let cst = build_cst(json);
3274 let root_value = cst.value().unwrap();
3275 let root_obj = root_value.as_object().unwrap();
3276 let prop = root_obj.get(prop_name).unwrap();
3277 prop.remove();
3278 assert_eq!(cst.to_string(), expected);
3279 }
3280
3281 run_test(
3282 "value2",
3283 r#"{
3284 "value": 5,
3285 // comment
3286 "value2": "hello",
3287 value3: true
3288}"#,
3289 r#"{
3290 "value": 5,
3291 // comment
3292 value3: true
3293}"#,
3294 );
3295
3296 run_test(
3297 "value2",
3298 r#"{
3299 "value": 5,
3300 // comment
3301 "value2": "hello"
3302 ,value3: true
3303}"#,
3304 r#"{
3306 "value": 5,
3307 // comment
3308value3: true
3309}"#,
3310 );
3311
3312 run_test("value", r#"{ "value": 5 }"#, r#"{}"#);
3313 run_test("value", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value2": 6 }"#);
3314 run_test("value2", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value": 5 }"#);
3315 }
3316
3317 #[test]
3318 fn insert_properties() {
3319 fn run_test(index: usize, prop_name: &str, value: CstInputValue, json: &str, expected: &str) {
3320 let cst = build_cst(json);
3321 let root_value = cst.value().unwrap();
3322 let root_obj = root_value.as_object().unwrap();
3323 root_obj.insert(index, prop_name, value);
3324 assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3325 }
3326
3327 run_test(
3328 0,
3329 "propName",
3330 json!([1]),
3331 r#"{}"#,
3332 r#"{
3333 "propName": [1]
3334}"#,
3335 );
3336
3337 run_test(
3339 0,
3340 "value0",
3341 json!([1]),
3342 r#"{
3343 "value1": 5
3344}"#,
3345 r#"{
3346 "value0": [1],
3347 "value1": 5
3348}"#,
3349 );
3350
3351 run_test(
3353 0,
3354 "value0",
3355 json!([1]),
3356 r#"{
3357 // some comment
3358 "value1": 5
3359}"#,
3360 r#"{
3361 "value0": [1],
3362 // some comment
3363 "value1": 5
3364}"#,
3365 );
3366
3367 run_test(
3369 1,
3370 "value1",
3371 json!({
3372 "value": 1
3373 }),
3374 r#"{
3375 "value0": 5 // comment
3376}"#,
3377 r#"{
3378 "value0": 5, // comment
3379 "value1": {
3380 "value": 1
3381 }
3382}"#,
3383 );
3384
3385 run_test(
3387 1,
3388 "propName",
3389 json!(true),
3390 r#"{
3391 "value": 4,
3392}"#,
3393 r#"{
3394 "value": 4,
3395 "propName": true,
3396}"#,
3397 );
3398
3399 run_test(
3401 1,
3402 "propName",
3403 json!(true),
3404 r#"{ "value": 4 }"#,
3405 r#"{
3406 "value": 4,
3407 "propName": true
3408}"#,
3409 );
3410
3411 run_test(
3413 1,
3414 "propName",
3415 json!(true),
3416 r#"{ "value": 4, }"#,
3417 r#"{
3418 "value": 4,
3419 "propName": true,
3420}"#,
3421 );
3422 }
3423
3424 #[test]
3425 fn remove_array_elements() {
3426 fn run_test(index: usize, json: &str, expected: &str) {
3427 let cst = build_cst(json);
3428 let root_value = cst.value().unwrap();
3429 let root_array = root_value.as_array().unwrap();
3430 let element = root_array.elements().get(index).unwrap().clone();
3431 element.remove();
3432 assert_eq!(cst.to_string(), expected);
3433 }
3434
3435 run_test(
3436 0,
3437 r#"[
3438 1,
3439]"#,
3440 r#"[]"#,
3441 );
3442 run_test(
3443 0,
3444 r#"[
3445 1,
3446 2,
3447]"#,
3448 r#"[
3449 2,
3450]"#,
3451 );
3452 run_test(
3453 0,
3454 r#"[
3455 1,
3456 2,
3457]"#,
3458 r#"[
3459 2,
3460]"#,
3461 );
3462
3463 run_test(
3464 1,
3465 r#"[
3466 1, // other comment
3467 2, // trailing comment
3468]"#,
3469 r#"[
3470 1, // other comment
3471]"#,
3472 );
3473
3474 run_test(
3475 1,
3476 r#"[
3477 1, // comment
3478 2
3479]"#,
3480 r#"[
3481 1 // comment
3482]"#,
3483 );
3484
3485 run_test(1, r#"[1, 2]"#, r#"[1]"#);
3486 run_test(1, r#"[ 1, 2 /* test */ ]"#, r#"[ 1 ]"#);
3487 run_test(1, r#"[1, /* test */ 2]"#, r#"[1]"#);
3488 run_test(
3489 1,
3490 r#"[1 /* a */, /* b */ 2 /* c */, /* d */ true]"#,
3491 r#"[1 /* a */, /* d */ true]"#,
3492 );
3493 }
3494
3495 #[test]
3496 fn insert_array_element() {
3497 #[track_caller]
3498 fn run_test(index: usize, value: CstInputValue, json: &str, expected: &str) {
3499 let cst = build_cst(json);
3500 let root_value = cst.value().unwrap();
3501 let root_array = root_value.as_array().unwrap();
3502 root_array.insert(index, value);
3503 assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3504 }
3505
3506 run_test(0, json!([1]), r#"[]"#, r#"[[1]]"#);
3507 run_test(0, json!([1, true, false, {}]), r#"[]"#, r#"[[1, true, false, {}]]"#);
3508 run_test(0, json!(10), r#"[]"#, r#"[10]"#);
3509 run_test(0, json!(10), r#"[1]"#, r#"[10, 1]"#);
3510 run_test(1, json!(10), r#"[1]"#, r#"[1, 10]"#);
3511 run_test(
3512 0,
3513 json!(10),
3514 r#"[
3515 1
3516]"#,
3517 r#"[
3518 10,
3519 1
3520]"#,
3521 );
3522 run_test(
3523 0,
3524 json!(10),
3525 r#"[
3526 /* test */ 1
3527]"#,
3528 r#"[
3529 10,
3530 /* test */ 1
3531]"#,
3532 );
3533
3534 run_test(
3535 0,
3536 json!({
3537 "value": 1,
3538 }),
3539 r#"[]"#,
3540 r#"[
3541 {
3542 "value": 1
3543 }
3544]"#,
3545 );
3546
3547 run_test(
3549 0,
3550 json!({
3551 "value": 1,
3552 }),
3553 r#"[
3554 // comment
3555]"#,
3556 r#"[
3557 // comment
3558 {
3559 "value": 1
3560 }
3561]"#,
3562 );
3563
3564 run_test(
3566 0,
3567 json!({
3568 "value": 1,
3569 }),
3570 r#"[
3571
3572]"#,
3573 r#"[
3574 {
3575 "value": 1
3576 }
3577]"#,
3578 );
3579 }
3580
3581 #[test]
3582 fn insert_array_element_trailing_commas() {
3583 let cst = build_cst(
3584 r#"{
3585 "prop": [
3586 1,
3587 2,
3588 ]
3589}"#,
3590 );
3591 cst
3592 .object_value_or_create()
3593 .unwrap()
3594 .array_value("prop")
3595 .unwrap()
3596 .append(json!(3));
3597 assert_eq!(
3598 cst.to_string(),
3599 r#"{
3600 "prop": [
3601 1,
3602 2,
3603 3,
3604 ]
3605}"#
3606 );
3607 }
3608
3609 #[test]
3610 fn remove_comment() {
3611 fn run_test(json: &str, expected: &str) {
3612 let cst = build_cst(json);
3613 let root_value = cst.value().unwrap();
3614 let root_obj = root_value.as_object().unwrap();
3615 root_obj
3616 .children()
3617 .into_iter()
3618 .filter_map(|c| c.as_comment())
3619 .next()
3620 .unwrap()
3621 .remove();
3622 assert_eq!(cst.to_string(), expected);
3623 }
3624
3625 run_test(
3626 r#"{
3627 "value": 5,
3628 // comment
3629 "value2": "hello",
3630 value3: true
3631}"#,
3632 r#"{
3633 "value": 5,
3634 "value2": "hello",
3635 value3: true
3636}"#,
3637 );
3638
3639 run_test(
3640 r#"{
3641 "value": 5, // comment
3642 "value2": "hello",
3643 value3: true
3644}"#,
3645 r#"{
3646 "value": 5,
3647 "value2": "hello",
3648 value3: true
3649}"#,
3650 );
3651 }
3652
3653 #[test]
3654 fn object_value_or_create() {
3655 {
3657 let cst = build_cst(r#"{ "value": 1 }"#);
3658 let obj = cst.object_value_or_create().unwrap();
3659 assert!(obj.get("value").is_some());
3660 }
3661 {
3663 let cst = build_cst(r#""#);
3664 cst.object_value_or_create().unwrap();
3665 assert_eq!(cst.to_string(), "{}\n");
3666 }
3667 {
3669 let cst = build_cst("// Copyright something");
3670 cst.object_value_or_create().unwrap();
3671 assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3672 }
3673 {
3675 let cst = build_cst("// Copyright something\n");
3676 cst.object_value_or_create().unwrap();
3677 assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3678 }
3679 }
3680
3681 #[test]
3682 fn array_ensure_multiline() {
3683 {
3685 let cst = build_cst(r#"[]"#);
3686 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3687 assert_eq!(cst.to_string(), "[\n]");
3688 }
3689 {
3691 let cst = build_cst(r#"[ ]"#);
3692 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3693 assert_eq!(cst.to_string(), "[\n]");
3694 }
3695 {
3697 let cst = build_cst(r#"[ /* test */ ]"#);
3698 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3699 assert_eq!(cst.to_string(), "[\n /* test */\n]");
3700 }
3701 {
3703 let cst = build_cst(r#"[ 1, 2, /* test */ 3 ]"#);
3704 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3705 assert_eq!(
3706 cst.to_string(),
3707 r#"[
3708 1,
3709 2,
3710 /* test */ 3
3711]"#
3712 );
3713 }
3714 {
3716 let cst = build_cst(
3717 r#"{
3718 "prop": {
3719 "value": [ 1, 2, /* test */ 3 ]
3720 }
3721}"#,
3722 );
3723 cst
3724 .value()
3725 .unwrap()
3726 .as_object()
3727 .unwrap()
3728 .get("prop")
3729 .unwrap()
3730 .value()
3731 .unwrap()
3732 .as_object()
3733 .unwrap()
3734 .get("value")
3735 .unwrap()
3736 .value()
3737 .unwrap()
3738 .as_array()
3739 .unwrap()
3740 .ensure_multiline();
3741 assert_eq!(
3742 cst.to_string(),
3743 r#"{
3744 "prop": {
3745 "value": [
3746 1,
3747 2,
3748 /* test */ 3
3749 ]
3750 }
3751}"#
3752 );
3753 }
3754 {
3756 let cst = build_cst("[ 1, 2, /* test */ 3 ]\r\n");
3757 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3758 assert_eq!(cst.to_string(), "[\r\n 1,\r\n 2,\r\n /* test */ 3\r\n]\r\n");
3759 }
3760 }
3761
3762 #[test]
3763 fn object_ensure_multiline() {
3764 {
3766 let cst = build_cst(r#"{}"#);
3767 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3768 assert_eq!(cst.to_string(), "{\n}");
3769 }
3770 {
3772 let cst = build_cst(r#"{ }"#);
3773 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3774 assert_eq!(cst.to_string(), "{\n}");
3775 }
3776 {
3778 let cst = build_cst(r#"{ /* test */ }"#);
3779 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3780 assert_eq!(cst.to_string(), "{\n /* test */\n}");
3781 }
3782 {
3784 let cst = build_cst(r#"{ prop: 1, prop2: 2, /* test */ prop3: 3 }"#);
3785 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3786 assert_eq!(
3787 cst.to_string(),
3788 r#"{
3789 prop: 1,
3790 prop2: 2,
3791 /* test */ prop3: 3
3792}"#
3793 );
3794 }
3795 {
3797 let cst = build_cst(
3798 r#"{
3799 "prop": {
3800 "value": { prop: 1, prop2: 2, /* test */ prop3: 3 }
3801 }
3802}"#,
3803 );
3804 cst
3805 .value()
3806 .unwrap()
3807 .as_object()
3808 .unwrap()
3809 .get("prop")
3810 .unwrap()
3811 .value()
3812 .unwrap()
3813 .as_object()
3814 .unwrap()
3815 .get("value")
3816 .unwrap()
3817 .value()
3818 .unwrap()
3819 .as_object()
3820 .unwrap()
3821 .ensure_multiline();
3822 assert_eq!(
3823 cst.to_string(),
3824 r#"{
3825 "prop": {
3826 "value": {
3827 prop: 1,
3828 prop2: 2,
3829 /* test */ prop3: 3
3830 }
3831 }
3832}"#
3833 );
3834 }
3835 }
3836
3837 #[test]
3838 fn sets_trailing_commas() {
3839 fn run_test(input: &str, mode: crate::cst::TrailingCommaMode, expected: &str) {
3840 let cst = build_cst(input);
3841 let root_value = cst.value().unwrap();
3842 let root_obj = root_value.as_object().unwrap();
3843 root_obj.set_trailing_commas(mode);
3844 assert_eq!(cst.to_string(), expected);
3845 }
3846
3847 run_test(
3849 r#"{
3850}"#,
3851 TrailingCommaMode::Never,
3852 r#"{
3853}"#,
3854 );
3855 run_test(
3856 r#"{
3857 // test
3858}"#,
3859 TrailingCommaMode::IfMultiline,
3860 r#"{
3861 // test
3862}"#,
3863 );
3864
3865 run_test(r#"{"a": 1}"#, TrailingCommaMode::Never, r#"{"a": 1}"#);
3867 run_test(r#"{"a": 1}"#, TrailingCommaMode::IfMultiline, r#"{"a": 1}"#);
3868 run_test(
3870 r#"{
3871 "a": 1,
3872 "b": 2,
3873 "c": [1, 2, 3],
3874 "d": [
3875 1
3876 ]
3877}"#,
3878 TrailingCommaMode::IfMultiline,
3879 r#"{
3880 "a": 1,
3881 "b": 2,
3882 "c": [1, 2, 3],
3883 "d": [
3884 1,
3885 ],
3886}"#,
3887 );
3888 run_test(
3889 r#"{
3890"a": 1,
3891"b": 2,
3892}"#,
3893 TrailingCommaMode::Never,
3894 r#"{
3895"a": 1,
3896"b": 2
3897}"#,
3898 );
3899 }
3900
3901 #[test]
3902 fn or_create_methods() {
3903 let cst = build_cst("");
3904 let obj = cst.object_value_or_create().unwrap();
3905 assert_eq!(cst.to_string(), "{}\n");
3906 assert!(cst.array_value_or_create().is_none());
3907 assert_eq!(obj.object_value_or_create("prop").unwrap().to_string(), "{}");
3908 assert!(obj.array_value_or_create("prop").is_none());
3909 assert_eq!(obj.array_value_or_create("prop2").unwrap().to_string(), "[]");
3910 assert_eq!(
3911 cst.to_string(),
3912 r#"{
3913 "prop": {},
3914 "prop2": []
3915}
3916"#
3917 );
3918 }
3919
3920 #[test]
3921 fn or_set_methods() {
3922 let cst = build_cst("");
3923 let array = cst.array_value_or_set();
3924 assert_eq!(array.to_string(), "[]");
3925 assert_eq!(cst.to_string(), "[]\n");
3926 let object = cst.object_value_or_set();
3927 assert_eq!(object.to_string(), "{}");
3928 assert_eq!(cst.to_string(), "{}\n");
3929 let value = object.array_value_or_set("test");
3930 assert_eq!(value.to_string(), "[]");
3931 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3932 let value = object.object_value_or_set("test");
3933 assert_eq!(value.to_string(), "{}");
3934 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3935 let value = object.array_value_or_set("test");
3936 assert_eq!(value.to_string(), "[]");
3937 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3938 value.append(json!(1));
3939 assert_eq!(cst.to_string(), "{\n \"test\": [1]\n}\n");
3940 let value = object.object_value_or_set("test");
3941 assert_eq!(value.to_string(), "{}");
3942 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3943 let test_prop = object.get("test").unwrap();
3944 assert!(test_prop.object_value().is_some());
3945 assert!(test_prop.array_value().is_none());
3946 test_prop.array_value_or_set();
3947 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3948 assert!(test_prop.object_value().is_none());
3949 assert!(test_prop.array_value().is_some());
3950 test_prop.object_value_or_set();
3951 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3952 }
3953
3954 #[test]
3955 fn expression_properties_and_values() {
3956 #[track_caller]
3957 fn run_test(value: CstInputValue, expected: &str) {
3958 let cst = build_cst("");
3959 cst.set_value(value);
3960 assert_eq!(cst.to_string(), format!("{}\n", expected));
3961 }
3962
3963 run_test(json!(1), "1");
3964 run_test(json!("test"), "\"test\"");
3965 {
3966 let text = "test";
3967 run_test(json!(text), "\"test\"");
3968 }
3969 {
3970 let num = 1;
3971 run_test(json!(num), "1");
3972 }
3973 {
3974 let vec = vec![1, 2, 3];
3975 run_test(json!(vec), "[1, 2, 3]");
3976 }
3977 {
3978 let vec = vec![1, 2, 3];
3979 run_test(
3980 json!({
3981 "value": vec,
3982 }),
3983 r#"{
3984 "value": [1, 2, 3]
3985}"#,
3986 );
3987 }
3988 run_test(
3989 json!({
3990 notQuoted: 1,
3991 "quoted": 2,
3992 }),
3993 r#"{
3994 "notQuoted": 1,
3995 "quoted": 2
3996}"#,
3997 )
3998 }
3999
4000 #[test]
4001 fn property_index() {
4002 let cst = build_cst("{ \"prop\": 1, \"prop2\": 2, \"prop3\": 3 }");
4003 let object = cst.object_value().unwrap();
4004 for (i, prop) in object.properties().into_iter().enumerate() {
4005 assert_eq!(prop.property_index(), i);
4006 }
4007 }
4008
4009 #[test]
4010 fn element_index() {
4011 let cst = build_cst("[1, 2, true ,false]");
4012 let array = cst.array_value().unwrap();
4013 for (i, prop) in array.elements().into_iter().enumerate() {
4014 assert_eq!(prop.element_index().unwrap(), i);
4015 }
4016 }
4017
4018 #[track_caller]
4019 fn build_cst(text: &str) -> CstRootNode {
4020 CstRootNode::parse(text, &crate::ParseOptions::default()).unwrap()
4021 }
4022
4023 #[cfg(feature = "serde")]
4024 mod serde_tests {
4025 use super::build_cst;
4026 use serde_json::Value as SerdeValue;
4027 use std::str::FromStr;
4028
4029 #[test]
4030 fn test_cst_to_serde_value_primitives() {
4031 let root = build_cst(r#"42"#);
4032 let value = root.to_serde_value().unwrap();
4033 assert_eq!(value, SerdeValue::Number(serde_json::Number::from_str("42").unwrap()));
4034
4035 let root = build_cst(r#""hello""#);
4036 let value = root.to_serde_value().unwrap();
4037 assert_eq!(value, SerdeValue::String("hello".to_string()));
4038
4039 let root = build_cst(r#"true"#);
4040 let value = root.to_serde_value().unwrap();
4041 assert_eq!(value, SerdeValue::Bool(true));
4042
4043 let root = build_cst(r#"false"#);
4044 let value = root.to_serde_value().unwrap();
4045 assert_eq!(value, SerdeValue::Bool(false));
4046
4047 let root = build_cst(r#"null"#);
4048 let value = root.to_serde_value().unwrap();
4049 assert_eq!(value, SerdeValue::Null);
4050 }
4051
4052 #[test]
4053 fn test_cst_to_serde_value_array() {
4054 let root = build_cst(r#"[1, 2, 3]"#);
4055 let value = root.to_serde_value().unwrap();
4056 let expected = SerdeValue::Array(vec![
4057 SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4058 SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4059 SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4060 ]);
4061 assert_eq!(value, expected);
4062 }
4063
4064 #[test]
4065 fn test_cst_to_serde_value_array_with_comments() {
4066 let root = build_cst(
4067 r#"[
4068 // comment 1
4069 1,
4070 2, // comment 2
4071 3
4072 ]"#,
4073 );
4074 let value = root.to_serde_value().unwrap();
4075 let expected = SerdeValue::Array(vec![
4076 SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4077 SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4078 SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4079 ]);
4080 assert_eq!(value, expected);
4081 }
4082
4083 #[test]
4084 fn test_cst_to_serde_value_object() {
4085 let root = build_cst(
4086 r#"{
4087 "name": "Alice",
4088 "age": 30,
4089 "active": true
4090 }"#,
4091 );
4092 let value = root.to_serde_value().unwrap();
4093
4094 let mut expected_map = serde_json::map::Map::new();
4095 expected_map.insert("name".to_string(), SerdeValue::String("Alice".to_string()));
4096 expected_map.insert(
4097 "age".to_string(),
4098 SerdeValue::Number(serde_json::Number::from_str("30").unwrap()),
4099 );
4100 expected_map.insert("active".to_string(), SerdeValue::Bool(true));
4101
4102 assert_eq!(value, SerdeValue::Object(expected_map));
4103 }
4104
4105 #[test]
4106 fn test_cst_to_serde_value_object_with_comments() {
4107 let root = build_cst(
4108 r#"{
4109 // This is a name
4110 "name": "Bob",
4111 /* age field */
4112 "age": 25
4113 }"#,
4114 );
4115 let value = root.to_serde_value().unwrap();
4116
4117 let mut expected_map = serde_json::map::Map::new();
4118 expected_map.insert("name".to_string(), SerdeValue::String("Bob".to_string()));
4119 expected_map.insert(
4120 "age".to_string(),
4121 SerdeValue::Number(serde_json::Number::from_str("25").unwrap()),
4122 );
4123
4124 assert_eq!(value, SerdeValue::Object(expected_map));
4125 }
4126
4127 #[test]
4128 fn test_cst_to_serde_value_nested() {
4129 let root = build_cst(
4130 r#"{
4131 "person": {
4132 "name": "Charlie",
4133 "hobbies": ["reading", "gaming"]
4134 },
4135 "count": 42
4136 }"#,
4137 );
4138 let value = root.to_serde_value().unwrap();
4139
4140 let mut hobbies = Vec::new();
4141 hobbies.push(SerdeValue::String("reading".to_string()));
4142 hobbies.push(SerdeValue::String("gaming".to_string()));
4143
4144 let mut person_map = serde_json::map::Map::new();
4145 person_map.insert("name".to_string(), SerdeValue::String("Charlie".to_string()));
4146 person_map.insert("hobbies".to_string(), SerdeValue::Array(hobbies));
4147
4148 let mut expected_map = serde_json::map::Map::new();
4149 expected_map.insert("person".to_string(), SerdeValue::Object(person_map));
4150 expected_map.insert(
4151 "count".to_string(),
4152 SerdeValue::Number(serde_json::Number::from_str("42").unwrap()),
4153 );
4154
4155 assert_eq!(value, SerdeValue::Object(expected_map));
4156 }
4157
4158 #[test]
4159 fn test_cst_to_serde_value_with_trailing_comma() {
4160 let root = build_cst(
4161 r#"{
4162 "a": 1,
4163 "b": 2,
4164 }"#,
4165 );
4166 let value = root.to_serde_value().unwrap();
4167
4168 let mut expected_map = serde_json::map::Map::new();
4169 expected_map.insert(
4170 "a".to_string(),
4171 SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4172 );
4173 expected_map.insert(
4174 "b".to_string(),
4175 SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4176 );
4177
4178 assert_eq!(value, SerdeValue::Object(expected_map));
4179 }
4180
4181 #[test]
4182 fn test_cst_to_serde_value_empty_structures() {
4183 let root = build_cst(r#"{}"#);
4184 let value = root.to_serde_value().unwrap();
4185 assert_eq!(value, SerdeValue::Object(serde_json::map::Map::new()));
4186
4187 let root = build_cst(r#"[]"#);
4188 let value = root.to_serde_value().unwrap();
4189 assert_eq!(value, SerdeValue::Array(Vec::new()));
4190 }
4191
4192 #[test]
4193 fn test_cst_to_serde_value_scientific_notation() {
4194 let root = build_cst(r#"0.3e+025"#);
4195 let value = root.to_serde_value().unwrap();
4196 assert_eq!(
4197 value,
4198 SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap())
4199 );
4200 }
4201
4202 #[test]
4203 fn test_cst_node_to_serde_value() {
4204 let root = build_cst(r#"{ "test": 123 }"#);
4205 let value_node = root.value().unwrap();
4206 let json_value = value_node.to_serde_value().unwrap();
4207
4208 let mut expected_map = serde_json::map::Map::new();
4209 expected_map.insert(
4210 "test".to_string(),
4211 SerdeValue::Number(serde_json::Number::from_str("123").unwrap()),
4212 );
4213
4214 assert_eq!(json_value, SerdeValue::Object(expected_map));
4215 }
4216
4217 #[test]
4218 fn test_cst_object_prop_to_serde_value() {
4219 let root = build_cst(r#"{ "key": [1, 2, 3] }"#);
4220 let obj = root.value().unwrap().as_object().unwrap();
4221 let prop = obj.get("key").unwrap();
4222 let prop_value = prop.to_serde_value().unwrap();
4223
4224 let expected = SerdeValue::Array(vec![
4225 SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4226 SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4227 SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4228 ]);
4229
4230 assert_eq!(prop_value, expected);
4231 }
4232 }
4233}