1use super::common::Range;
2use super::common::Ranged;
3use std::borrow::Cow;
4
5#[derive(Debug, PartialEq, Clone)]
7pub enum Value<'a> {
8 StringLit(StringLit<'a>),
9 NumberLit(NumberLit<'a>),
10 BooleanLit(BooleanLit),
11 Object(Object<'a>),
12 Array(Array<'a>),
13 NullKeyword(NullKeyword),
14}
15
16impl<'a> Value<'a> {
17 pub fn as_string_lit(&self) -> Option<&StringLit<'a>> {
18 match self {
19 Value::StringLit(node) => Some(node),
20 _ => None,
21 }
22 }
23
24 pub fn as_number_lit(&self) -> Option<&NumberLit<'a>> {
25 match self {
26 Value::NumberLit(node) => Some(node),
27 _ => None,
28 }
29 }
30
31 pub fn as_boolean_lit(&self) -> Option<&BooleanLit> {
32 match self {
33 Value::BooleanLit(node) => Some(node),
34 _ => None,
35 }
36 }
37
38 pub fn as_object(&self) -> Option<&Object<'a>> {
39 match self {
40 Value::Object(node) => Some(node),
41 _ => None,
42 }
43 }
44
45 pub fn as_array(&self) -> Option<&Array<'a>> {
46 match self {
47 Value::Array(node) => Some(node),
48 _ => None,
49 }
50 }
51
52 pub fn as_null_keyword(&self) -> Option<&NullKeyword> {
53 match self {
54 Value::NullKeyword(node) => Some(node),
55 _ => None,
56 }
57 }
58}
59
60#[cfg(feature = "serde")]
61impl<'a> From<Value<'a>> for serde_json::Value {
62 fn from(value: Value<'a>) -> Self {
63 use std::str::FromStr;
64 match value {
65 Value::Array(arr) => {
66 let vec = arr.elements.into_iter().map(|v| v.into()).collect();
67 serde_json::Value::Array(vec)
68 }
69 Value::BooleanLit(b) => serde_json::Value::Bool(b.value),
70 Value::NullKeyword(_) => serde_json::Value::Null,
71 Value::NumberLit(num) => {
72 let num_str = num.value.trim_start_matches(['-', '+']);
74 if num_str.len() > 2 && (num_str.starts_with("0x") || num_str.starts_with("0X")) {
75 let hex_part = &num_str[2..];
77 match i64::from_str_radix(hex_part, 16) {
78 Ok(decimal_value) => {
79 let final_value = if num.value.starts_with('-') {
80 -decimal_value
81 } else {
82 decimal_value
83 };
84 serde_json::Value::Number(serde_json::Number::from(final_value))
85 }
86 Err(_) => serde_json::Value::String(num.value.to_string()),
87 }
88 } else {
89 let num_for_parsing = num.value.trim_start_matches('+');
91 match serde_json::Number::from_str(num_for_parsing) {
92 Ok(number) => serde_json::Value::Number(number),
93 Err(_) => serde_json::Value::String(num.value.to_string()),
94 }
95 }
96 }
97 Value::Object(obj) => {
98 let mut map = serde_json::map::Map::new();
99 for prop in obj.properties {
100 map.insert(prop.name.into_string(), prop.value.into());
101 }
102 serde_json::Value::Object(map)
103 }
104 Value::StringLit(s) => serde_json::Value::String(s.value.into_owned()),
105 }
106 }
107}
108
109#[derive(Debug, PartialEq, Clone, Copy)]
111pub enum Node<'a, 'b> {
112 StringLit(&'b StringLit<'a>),
113 NumberLit(&'b NumberLit<'a>),
114 BooleanLit(&'b BooleanLit),
115 Object(&'b Object<'a>),
116 ObjectProp(&'b ObjectProp<'a>),
117 Array(&'b Array<'a>),
118 NullKeyword(&'b NullKeyword),
119 WordLit(&'b WordLit<'a>),
120}
121
122impl<'a, 'b> Node<'a, 'b> {
123 pub fn kind(&self) -> NodeKind {
125 match self {
126 Node::StringLit(_) => NodeKind::StringLit,
127 Node::NumberLit(_) => NodeKind::NumberLit,
128 Node::BooleanLit(_) => NodeKind::BooleanLit,
129 Node::Object(_) => NodeKind::Object,
130 Node::ObjectProp(_) => NodeKind::ObjectProp,
131 Node::Array(_) => NodeKind::Array,
132 Node::NullKeyword(_) => NodeKind::NullKeyword,
133 Node::WordLit(_) => NodeKind::WordLit,
134 }
135 }
136
137 pub fn as_string_lit(&self) -> Option<&'b StringLit<'a>> {
138 match self {
139 Node::StringLit(node) => Some(node),
140 _ => None,
141 }
142 }
143
144 pub fn as_number_lit(&self) -> Option<&'b NumberLit<'a>> {
145 match self {
146 Node::NumberLit(node) => Some(node),
147 _ => None,
148 }
149 }
150
151 pub fn as_boolean_lit(&self) -> Option<&'b BooleanLit> {
152 match self {
153 Node::BooleanLit(node) => Some(node),
154 _ => None,
155 }
156 }
157
158 pub fn as_object(&self) -> Option<&'b Object<'a>> {
159 match self {
160 Node::Object(node) => Some(node),
161 _ => None,
162 }
163 }
164
165 pub fn as_object_prop(&self) -> Option<&'b ObjectProp<'a>> {
166 match self {
167 Node::ObjectProp(node) => Some(node),
168 _ => None,
169 }
170 }
171
172 pub fn as_array(&self) -> Option<&'b Array<'a>> {
173 match self {
174 Node::Array(node) => Some(node),
175 _ => None,
176 }
177 }
178
179 pub fn as_null_keyword(&self) -> Option<&'b NullKeyword> {
180 match self {
181 Node::NullKeyword(node) => Some(node),
182 _ => None,
183 }
184 }
185
186 pub fn as_word_lit(&self) -> Option<&'b WordLit<'a>> {
187 match self {
188 Node::WordLit(node) => Some(node),
189 _ => None,
190 }
191 }
192}
193
194#[derive(Debug, PartialEq, Clone, Copy)]
196pub enum NodeKind {
197 StringLit,
198 NumberLit,
199 BooleanLit,
200 Object,
201 ObjectProp,
202 Array,
203 NullKeyword,
204 WordLit,
205}
206
207#[derive(Debug, PartialEq, Clone)]
209pub struct StringLit<'a> {
210 pub range: Range,
211 pub value: Cow<'a, str>,
212}
213
214#[derive(Debug, PartialEq, Clone)]
217pub struct WordLit<'a> {
218 pub range: Range,
219 pub value: &'a str,
220}
221
222#[derive(Debug, PartialEq, Clone)]
224pub struct NumberLit<'a> {
225 pub range: Range,
226 pub value: &'a str,
227}
228
229#[derive(Debug, PartialEq, Clone)]
231pub struct BooleanLit {
232 pub range: Range,
233 pub value: bool,
234}
235
236#[derive(Debug, PartialEq, Clone)]
238pub struct NullKeyword {
239 pub range: Range,
240}
241
242#[derive(Debug, PartialEq, Clone)]
244pub struct Object<'a> {
245 pub range: Range,
246 pub properties: Vec<ObjectProp<'a>>,
247}
248
249macro_rules! generate_take {
250 ($self:ident, $name:ident, $value_type:ident) => {
251 if let Some(pos) = $self.properties.iter().position(|p| p.name.as_str() == $name) {
253 if let Value::$value_type(_) = &$self.properties[pos].value {
254 if let Value::$value_type(node) = $self.properties.remove(pos).value {
255 Some(node)
256 } else {
257 None
258 }
259 } else {
260 None
261 }
262 } else {
263 None
264 }
265 };
266}
267
268macro_rules! generate_get {
269 ($self:ident, $name:ident, $value_type:ident) => {
270 $self
271 .properties
272 .iter()
273 .filter(|p| p.name.as_str() == $name)
274 .map(|p| {
275 if let Value::$value_type(node) = &p.value {
276 Some(node)
277 } else {
278 None
279 }
280 })
281 .next()
282 .flatten()
283 };
284}
285
286impl<'a> Object<'a> {
287 pub fn get(&self, name: &str) -> Option<&ObjectProp<'a>> {
289 self.properties.iter().find(|p| p.name.as_str() == name)
290 }
291
292 pub fn get_string(&self, name: &str) -> Option<&StringLit<'a>> {
295 generate_get!(self, name, StringLit)
296 }
297
298 pub fn get_number(&self, name: &str) -> Option<&NumberLit<'a>> {
301 generate_get!(self, name, NumberLit)
302 }
303
304 pub fn get_boolean(&self, name: &str) -> Option<&BooleanLit> {
307 generate_get!(self, name, BooleanLit)
308 }
309
310 pub fn get_object(&self, name: &str) -> Option<&Object<'a>> {
313 generate_get!(self, name, Object)
314 }
315
316 pub fn get_array(&self, name: &str) -> Option<&Array<'a>> {
319 generate_get!(self, name, Array)
320 }
321
322 pub fn take(&mut self, name: &str) -> Option<ObjectProp<'a>> {
325 if let Some(pos) = self.properties.iter().position(|p| p.name.as_str() == name) {
326 Some(self.properties.remove(pos))
327 } else {
328 None
329 }
330 }
331
332 pub fn take_string(&mut self, name: &str) -> Option<StringLit<'a>> {
335 generate_take!(self, name, StringLit)
336 }
337
338 pub fn take_number(&mut self, name: &str) -> Option<NumberLit<'a>> {
341 generate_take!(self, name, NumberLit)
342 }
343
344 pub fn take_boolean(&mut self, name: &str) -> Option<BooleanLit> {
347 generate_take!(self, name, BooleanLit)
348 }
349
350 pub fn take_object(&mut self, name: &str) -> Option<Object<'a>> {
353 generate_take!(self, name, Object)
354 }
355
356 pub fn take_array(&mut self, name: &str) -> Option<Array<'a>> {
359 generate_take!(self, name, Array)
360 }
361}
362
363#[derive(Debug, PartialEq, Clone)]
365pub struct ObjectProp<'a> {
366 pub range: Range,
367 pub name: ObjectPropName<'a>,
368 pub value: Value<'a>,
369}
370
371#[derive(Debug, PartialEq, Clone)]
373pub enum ObjectPropName<'a> {
374 String(StringLit<'a>),
375 Word(WordLit<'a>),
376}
377
378impl<'a> ObjectPropName<'a> {
379 pub fn into_string(self) -> String {
381 match self {
382 ObjectPropName::String(lit) => lit.value.into_owned(),
383 ObjectPropName::Word(lit) => lit.value.to_string(),
384 }
385 }
386
387 pub fn as_str(&'a self) -> &'a str {
389 match self {
390 ObjectPropName::String(lit) => lit.value.as_ref(),
391 ObjectPropName::Word(lit) => lit.value,
392 }
393 }
394}
395
396#[derive(Debug, PartialEq, Clone)]
398pub struct Array<'a> {
399 pub range: Range,
400 pub elements: Vec<Value<'a>>,
401}
402
403#[derive(Debug, PartialEq, Clone)]
405pub enum CommentKind {
406 Line,
407 Block,
408}
409
410#[derive(Debug, PartialEq, Clone)]
412pub enum Comment<'a> {
413 Line(CommentLine<'a>),
414 Block(CommentBlock<'a>),
415}
416
417impl<'a> Comment<'a> {
418 pub fn text(&self) -> &'a str {
420 match self {
421 Comment::Line(line) => line.text,
422 Comment::Block(line) => line.text,
423 }
424 }
425
426 pub fn kind(&self) -> CommentKind {
428 match self {
429 Comment::Line(_) => CommentKind::Line,
430 Comment::Block(_) => CommentKind::Block,
431 }
432 }
433}
434
435impl<'a> Ranged for Comment<'a> {
436 fn range(&self) -> Range {
437 match self {
438 Comment::Line(line) => line.range(),
439 Comment::Block(line) => line.range(),
440 }
441 }
442}
443
444#[derive(Debug, PartialEq, Clone)]
446pub struct CommentLine<'a> {
447 pub range: Range,
448 pub text: &'a str,
449}
450
451#[derive(Debug, PartialEq, Clone)]
453pub struct CommentBlock<'a> {
454 pub range: Range,
455 pub text: &'a str,
456}
457
458impl<'a, 'b> From<&'b ObjectPropName<'a>> for Node<'a, 'b> {
461 fn from(object_prop_name: &'b ObjectPropName<'a>) -> Node<'a, 'b> {
462 match object_prop_name {
463 ObjectPropName::String(lit) => lit.into(),
464 ObjectPropName::Word(lit) => lit.into(),
465 }
466 }
467}
468
469impl<'a> Ranged for ObjectPropName<'a> {
470 fn range(&self) -> Range {
471 match self {
472 ObjectPropName::String(lit) => lit.range(),
473 ObjectPropName::Word(lit) => lit.range(),
474 }
475 }
476}
477
478macro_rules! impl_ranged {
481 ($($node_name:ident),*) => {
482 $(
483 impl Ranged for $node_name {
484 fn range(&self) -> Range {
485 self.range
486 }
487 }
488 )*
489 };
490}
491
492impl_ranged![BooleanLit, NullKeyword];
493
494macro_rules! impl_ranged_lifetime {
495 ($($node_name:ident),*) => {
496 $(
497 impl<'a> Ranged for $node_name<'a> {
498 fn range(&self) -> Range {
499 self.range
500 }
501 }
502 )*
503 };
504}
505
506impl_ranged_lifetime![
507 WordLit,
508 Object,
509 ObjectProp,
510 Array,
511 CommentLine,
512 CommentBlock,
513 NumberLit,
514 StringLit
515];
516
517impl<'a> Ranged for Value<'a> {
518 fn range(&self) -> Range {
519 match self {
520 Value::Array(node) => node.range(),
521 Value::BooleanLit(node) => node.range(),
522 Value::NullKeyword(node) => node.range(),
523 Value::NumberLit(node) => node.range(),
524 Value::Object(node) => node.range(),
525 Value::StringLit(node) => node.range(),
526 }
527 }
528}
529
530impl<'a, 'b> Ranged for Node<'a, 'b> {
531 fn range(&self) -> Range {
532 match self {
533 Node::StringLit(node) => node.range(),
534 Node::NumberLit(node) => node.range(),
535 Node::BooleanLit(node) => node.range(),
536 Node::NullKeyword(node) => node.range(),
537 Node::WordLit(node) => node.range(),
538 Node::Array(node) => node.range(),
539 Node::Object(node) => node.range(),
540 Node::ObjectProp(node) => node.range(),
541 }
542 }
543}
544
545macro_rules! generate_node {
546 ($($node_name:ident),*) => {
547 $(
548 impl<'a, 'b> From<&'b $node_name> for Node<'a, 'b> {
549 fn from(node: &'b $node_name) -> Node<'a, 'b> {
550 Node::$node_name(node)
551 }
552 }
553 )*
554 };
555}
556
557generate_node![BooleanLit, NullKeyword];
558
559macro_rules! generate_node_lifetime {
560 ($($node_name:ident),*) => {
561
562 $(
563 impl<'a, 'b> From<&'b $node_name<'a>> for Node<'a, 'b> {
564 fn from(node: &'b $node_name<'a>) -> Node<'a, 'b> {
565 Node::$node_name(node)
566 }
567 }
568 )*
569 };
570}
571
572generate_node_lifetime![WordLit, Object, ObjectProp, Array, NumberLit, StringLit];
573
574impl<'a, 'b> From<&'b Value<'a>> for Node<'a, 'b> {
575 fn from(value: &'b Value<'a>) -> Node<'a, 'b> {
576 match value {
577 Value::Array(node) => Node::Array(node),
578 Value::BooleanLit(node) => Node::BooleanLit(node),
579 Value::NullKeyword(node) => Node::NullKeyword(node),
580 Value::NumberLit(node) => Node::NumberLit(node),
581 Value::Object(node) => Node::Object(node),
582 Value::StringLit(node) => Node::StringLit(node),
583 }
584 }
585}
586
587#[cfg(test)]
588mod test {
589 use super::*;
590 use crate::ParseOptions;
591 use crate::parse_to_ast;
592
593 #[test]
594 fn it_should_take() {
595 let ast = parse_to_ast(
596 "{'prop': 'asdf', 'other': 'text'}",
597 &Default::default(),
598 &ParseOptions::default(),
599 )
600 .unwrap();
601 let mut obj = match ast.value {
602 Some(Value::Object(obj)) => obj,
603 _ => unreachable!(),
604 };
605
606 assert_eq!(obj.properties.len(), 2);
607 assert_eq!(obj.take_string("asdf"), None);
608 assert_eq!(obj.properties.len(), 2);
609 assert_eq!(obj.take_number("prop"), None);
610 assert_eq!(obj.properties.len(), 2);
611 assert!(obj.take_string("prop").is_some());
612 assert_eq!(obj.properties.len(), 1);
613 assert_eq!(obj.take("something"), None);
614 assert_eq!(obj.properties.len(), 1);
615 assert!(obj.take("other").is_some());
616 assert_eq!(obj.properties.len(), 0);
617 }
618
619 #[test]
620 fn it_should_get() {
621 let ast = parse_to_ast("{'prop': 'asdf'}", &Default::default(), &ParseOptions::default()).unwrap();
622 let obj = match ast.value {
623 Some(Value::Object(obj)) => obj,
624 _ => unreachable!(),
625 };
626
627 assert_eq!(obj.properties.len(), 1);
628 assert_eq!(obj.get_string("asdf"), None);
629 assert!(obj.get_string("prop").is_some());
630 assert_eq!(obj.get("asdf"), None);
631 assert_eq!(obj.properties.len(), 1);
632 }
633
634 #[cfg(feature = "serde")]
635 #[test]
636 fn it_should_coerce_to_serde_value() {
637 let ast = parse_to_ast(
638 r#"{"prop":[true,1,null,"str"]}"#,
639 &Default::default(),
640 &ParseOptions::default(),
641 )
642 .unwrap();
643 let value = ast.value.unwrap();
644 let serde_value: serde_json::Value = value.into();
645
646 assert_eq!(
647 serde_value,
648 serde_json::json!({
649 "prop": [
650 true,
651 1,
652 null,
653 "str"
654 ]
655 })
656 );
657 }
658
659 #[cfg(feature = "serde")]
660 #[test]
661 fn handle_weird_data() {
662 let ast = parse_to_ast(
663 r#"{eyyyyyyy:6yy:6000e000615yyyk:6}"#,
664 &Default::default(),
665 &ParseOptions::default(),
666 )
667 .unwrap();
668 let value = ast.value.unwrap();
669 let serde_value: serde_json::Value = value.into();
670
671 assert_eq!(
672 serde_value,
673 serde_json::json!({
675 "eyyyyyyy": 6,
676 "yy": "6000e000615",
677 "yyyk": 6
678 })
679 );
680 }
681}