jsona_ast/
lib.rs

1//! The JSONA abstract syntax tree module.
2
3pub use jsona::util::mapper::{Mapper, Position, Range};
4use serde::{Deserialize, Serialize};
5use serde_json::{Number as JsonNumber, Value};
6use std::{str::FromStr, string::String as StdString};
7
8use jsona::dom::{self, DomNode, Node};
9use jsona::error::ErrorObject;
10
11#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
12#[serde(tag = "type", rename_all = "camelCase")]
13pub enum Ast {
14    Null(Null),
15    Bool(Bool),
16    Number(Number),
17    String(String),
18    Array(Array),
19    Object(Object),
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
23pub struct Null {
24    pub annotations: Vec<Annotation>,
25    pub range: Option<Range>,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
29pub struct Bool {
30    pub value: bool,
31    pub annotations: Vec<Annotation>,
32    pub range: Option<Range>,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
36pub struct Number {
37    pub value: JsonNumber,
38    pub annotations: Vec<Annotation>,
39    pub range: Option<Range>,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
43pub struct String {
44    pub value: StdString,
45    pub annotations: Vec<Annotation>,
46    pub range: Option<Range>,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
50pub struct Array {
51    pub items: Vec<Ast>,
52    pub annotations: Vec<Annotation>,
53    pub range: Option<Range>,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
57pub struct Object {
58    pub properties: Vec<Property>,
59    pub annotations: Vec<Annotation>,
60    pub range: Option<Range>,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
64pub struct Property {
65    pub key: Key,
66    pub value: Ast,
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
70pub struct Annotation {
71    pub key: Key,
72    pub value: AnnotationValue,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
76pub struct Key {
77    pub name: StdString,
78    pub range: Option<Range>,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
82pub struct AnnotationValue {
83    pub value: Value,
84    pub range: Option<Range>,
85}
86
87impl FromStr for Ast {
88    type Err = Vec<ErrorObject>;
89
90    fn from_str(s: &str) -> Result<Self, Self::Err> {
91        let mapper = Mapper::new_utf16(s, false);
92        match s.parse::<Node>() {
93            Ok(value) => Ok(node_to_ast(&value, &mapper)),
94            Err(error) => Err(error.to_error_objects(&mapper)),
95        }
96    }
97}
98
99impl From<Ast> for Node {
100    fn from(ast: Ast) -> Self {
101        match ast {
102            Ast::Null(Null { annotations, .. }) => {
103                dom::Null::new(from_annotations(annotations)).into()
104            }
105            Ast::Bool(Bool {
106                value, annotations, ..
107            }) => dom::Bool::new(value, from_annotations(annotations)).into(),
108            Ast::Number(Number {
109                value, annotations, ..
110            }) => dom::Number::new(value, from_annotations(annotations)).into(),
111            Ast::String(String {
112                value, annotations, ..
113            }) => dom::String::new(value, from_annotations(annotations)).into(),
114            Ast::Array(Array {
115                items, annotations, ..
116            }) => {
117                let items: Vec<Node> = items.into_iter().map(Node::from).collect();
118                dom::Array::new(items, from_annotations(annotations)).into()
119            }
120            Ast::Object(Object {
121                properties,
122                annotations,
123                ..
124            }) => {
125                let mut props = dom::Map::default();
126                for prop in properties {
127                    props.add(
128                        dom::Key::property(prop.key.name),
129                        Node::from(prop.value),
130                        None,
131                    );
132                }
133                dom::Object::new(props, from_annotations(annotations)).into()
134            }
135        }
136    }
137}
138
139fn node_to_ast(value: &Node, mapper: &Mapper) -> Ast {
140    let mut annotations: Vec<Annotation> = vec![];
141    if let Some(value_annotations) = value.annotations() {
142        for (key, value) in value_annotations.value().read().iter() {
143            let key_range = key.mapper_range(mapper);
144            let value_range = value.mapper_range(mapper);
145            annotations.push({
146                Annotation {
147                    key: Key {
148                        name: key.value().to_string(),
149                        range: key_range,
150                    },
151                    value: AnnotationValue {
152                        value: value.to_plain_json(),
153                        range: value_range,
154                    },
155                }
156            });
157        }
158    }
159    let range = value.mapper_range(mapper);
160    match value {
161        Node::Null(_) => Ast::Null(Null { annotations, range }),
162        Node::Bool(v) => Ast::Bool(Bool {
163            value: v.value(),
164            annotations,
165            range,
166        }),
167        Node::Number(v) => Ast::Number(Number {
168            value: v.value().clone(),
169            annotations,
170            range,
171        }),
172        Node::String(v) => Ast::String(String {
173            value: v.value().to_string(),
174            annotations,
175            range,
176        }),
177        Node::Array(v) => {
178            let elements = v
179                .value()
180                .read()
181                .iter()
182                .map(|v| node_to_ast(v, mapper))
183                .collect();
184            Ast::Array(Array {
185                items: elements,
186                annotations,
187                range,
188            })
189        }
190        Node::Object(v) => {
191            let mut properties: Vec<Property> = vec![];
192            for (key, value) in v.value().read().iter() {
193                let range = key.mapper_range(mapper);
194                properties.push({
195                    Property {
196                        key: Key {
197                            name: key.value().to_string(),
198                            range,
199                        },
200                        value: node_to_ast(value, mapper),
201                    }
202                });
203            }
204            Ast::Object(Object {
205                properties,
206                annotations,
207                range,
208            })
209        }
210    }
211}
212
213fn from_annotations(annotations: Vec<Annotation>) -> Option<dom::Annotations> {
214    if annotations.is_empty() {
215        return None;
216    }
217    let mut map = dom::Map::default();
218    for anno in annotations {
219        map.add(
220            dom::Key::annotation(anno.key.name),
221            serde_json::from_value(anno.value.value).unwrap(),
222            None,
223        )
224    }
225    Some(dom::Annotations::new(map))
226}