eure_document/document/
node.rs

1use crate::{prelude_internal::*, value::ValueKind};
2
3#[derive(Debug)]
4/// A node in the Eure document.
5///
6/// This does not implement PartialEq since content may refer to other nodes, and so equality is not well-defined.
7pub struct Node {
8    pub content: NodeValue,
9    pub extensions: Map<Identifier, NodeId>,
10}
11
12pub struct NodeMut<'d> {
13    document: &'d mut EureDocument,
14    pub node_id: NodeId,
15}
16
17impl<'d> core::fmt::Debug for NodeMut<'d> {
18    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19        match self.document.get_node(self.node_id) {
20            Some(node) => f
21                .debug_tuple("NodeMut")
22                .field(&self.node_id)
23                .field(node)
24                .finish(),
25            None => f
26                .debug_tuple("NodeMut")
27                .field(&self.node_id)
28                .field(&"<invalid>")
29                .finish(),
30        }
31    }
32}
33
34impl<'d> NodeMut<'d> {
35    pub fn new(document: &'d mut EureDocument, node_id: NodeId) -> Self {
36        Self { document, node_id }
37    }
38
39    pub fn add_map_child(self, object_key: ObjectKey) -> Result<NodeMut<'d>, InsertErrorKind> {
40        self.document.add_map_child(object_key, self.node_id)
41    }
42
43    pub fn add_extension(self, identifier: Identifier) -> Result<NodeMut<'d>, InsertErrorKind> {
44        self.document.add_extension(identifier, self.node_id)
45    }
46
47    pub fn add_tuple_element(self, index: u8) -> Result<NodeMut<'d>, InsertErrorKind> {
48        self.document.add_tuple_element(index, self.node_id)
49    }
50
51    pub fn add_array_element(self, index: Option<usize>) -> Result<NodeMut<'d>, InsertErrorKind> {
52        self.document.add_array_element(index, self.node_id)
53    }
54
55    pub fn add_child_by_segment(
56        self,
57        segment: PathSegment,
58    ) -> Result<NodeMut<'d>, InsertErrorKind> {
59        self.document.add_child_by_segment(segment, self.node_id)
60    }
61
62    pub fn get_extension(self, ident: &Identifier) -> Option<NodeMut<'d>> {
63        let node_id = self.document.node(self.node_id).extensions.get(ident)?;
64        Some(NodeMut::new(self.document, *node_id))
65    }
66
67    // Content access methods
68
69    pub fn as_map(self) -> Option<&'d NodeMap> {
70        self.document.node(self.node_id).as_map()
71    }
72
73    pub fn as_array(self) -> Option<&'d NodeArray> {
74        self.document.node(self.node_id).as_array()
75    }
76
77    pub fn as_tuple(self) -> Option<&'d NodeTuple> {
78        self.document.node(self.node_id).as_tuple()
79    }
80
81    pub fn require_map(self) -> Result<&'d mut NodeMap, InsertErrorKind> {
82        self.document.node_mut(self.node_id).require_map()
83    }
84
85    pub fn require_tuple(self) -> Result<&'d mut NodeTuple, InsertErrorKind> {
86        self.document.node_mut(self.node_id).require_tuple()
87    }
88
89    pub fn require_array(self) -> Result<&'d mut NodeArray, InsertErrorKind> {
90        self.document.node_mut(self.node_id).require_array()
91    }
92}
93
94impl Node {
95    pub fn as_map(&self) -> Option<&NodeMap> {
96        match &self.content {
97            NodeValue::Map(map) => Some(map),
98            _ => None,
99        }
100    }
101
102    pub fn as_array(&self) -> Option<&NodeArray> {
103        match &self.content {
104            NodeValue::Array(array) => Some(array),
105            _ => None,
106        }
107    }
108
109    pub fn as_tuple(&self) -> Option<&NodeTuple> {
110        match &self.content {
111            NodeValue::Tuple(tuple) => Some(tuple),
112            _ => None,
113        }
114    }
115
116    pub fn as_primitive(&self) -> Option<&PrimitiveValue> {
117        match &self.content {
118            NodeValue::Primitive(primitive) => Some(primitive),
119            _ => None,
120        }
121    }
122
123    pub fn get_extension(&self, ident: &Identifier) -> Option<NodeId> {
124        self.extensions.get(ident).copied()
125    }
126
127    pub(crate) fn require_map(&mut self) -> Result<&mut NodeMap, InsertErrorKind> {
128        if self.content == NodeValue::Hole {
129            self.content = NodeValue::Map(Default::default());
130            let NodeValue::Map(map) = &mut self.content else {
131                unreachable!();
132            };
133            Ok(map)
134        } else if let NodeValue::Map(map) = &mut self.content {
135            Ok(map)
136        } else {
137            Err(InsertErrorKind::ExpectedMap)
138        }
139    }
140
141    pub(crate) fn require_tuple(&mut self) -> Result<&mut NodeTuple, InsertErrorKind> {
142        if self.content == NodeValue::Hole {
143            self.content = NodeValue::Tuple(Default::default());
144            let NodeValue::Tuple(tuple) = &mut self.content else {
145                unreachable!();
146            };
147            Ok(tuple)
148        } else if let NodeValue::Tuple(tuple) = &mut self.content {
149            Ok(tuple)
150        } else {
151            Err(InsertErrorKind::ExpectedTuple)
152        }
153    }
154
155    pub(crate) fn require_array(&mut self) -> Result<&mut NodeArray, InsertErrorKind> {
156        if self.content == NodeValue::Hole {
157            self.content = NodeValue::Array(Default::default());
158            let NodeValue::Array(array) = &mut self.content else {
159                unreachable!();
160            };
161            Ok(array)
162        } else if let NodeValue::Array(array) = &mut self.content {
163            Ok(array)
164        } else {
165            Err(InsertErrorKind::ExpectedArray)
166        }
167    }
168}
169
170#[derive(Debug, PartialEq, Clone)]
171pub enum NodeValue {
172    /// A node that has not any value.
173    Hole,
174    Primitive(PrimitiveValue),
175    Array(NodeArray),
176    Map(NodeMap),
177    Tuple(NodeTuple),
178}
179
180impl NodeValue {
181    pub fn empty_map() -> Self {
182        Self::Map(NodeMap::new())
183    }
184
185    pub fn empty_array() -> Self {
186        Self::Array(NodeArray::new())
187    }
188
189    pub fn empty_tuple() -> Self {
190        Self::Tuple(NodeTuple::new())
191    }
192
193    pub fn value_kind(&self) -> Option<ValueKind> {
194        match self {
195            Self::Hole => None,
196            Self::Primitive(primitive) => Some(primitive.kind()),
197            Self::Array(_) => Some(ValueKind::Array),
198            Self::Map(_) => Some(ValueKind::Map),
199            Self::Tuple(_) => Some(ValueKind::Tuple),
200        }
201    }
202}
203
204// ============================================================================
205// From implementations for NodeValue
206// ============================================================================
207
208impl From<PrimitiveValue> for NodeValue {
209    fn from(p: PrimitiveValue) -> Self {
210        NodeValue::Primitive(p)
211    }
212}
213
214// TODO: Remove `pub`
215#[derive(Debug, Default, Clone, PartialEq, Eq, Plural)]
216pub struct NodeArray(pub Vec<NodeId>);
217
218// TODO: Remove `pub`
219#[derive(Debug, Default, Clone, PartialEq, Eq, Plural)]
220#[plural(len, is_empty, iter, into_iter, into_iter_ref, new)]
221pub struct NodeMap(pub Map<ObjectKey, NodeId>);
222
223// TODO: Remove `pub`
224#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Plural)]
225pub struct NodeTuple(pub Vec<NodeId>);
226
227impl NodeMap {
228    pub fn get(&self, key: &ObjectKey) -> Option<NodeId> {
229        self.0.get(key).copied()
230    }
231
232    pub fn add(&mut self, key: ObjectKey, node_id: NodeId) -> Result<(), InsertErrorKind> {
233        if self.0.contains_key(&key) {
234            return Err(InsertErrorKind::AlreadyAssigned { key });
235        }
236        self.0.insert(key, node_id);
237        Ok(())
238    }
239
240    pub fn replace(&mut self, key: ObjectKey, node_id: NodeId) {
241        self.0.insert(key, node_id);
242    }
243
244    pub fn remove(&mut self, key: &ObjectKey) -> Option<NodeId> {
245        self.0.remove(key)
246    }
247}
248
249impl NodeTuple {
250    pub fn get(&self, index: usize) -> Option<NodeId> {
251        self.0.get(index).copied()
252    }
253
254    pub fn push(&mut self, node_id: NodeId) -> Result<(), InsertErrorKind> {
255        self.0.push(node_id);
256        Ok(())
257    }
258
259    pub fn add_at(&mut self, index: u8, node_id: NodeId) -> Result<(), InsertErrorKind> {
260        if index as usize != self.0.len() {
261            return Err(InsertErrorKind::TupleIndexInvalid {
262                index,
263                expected_index: self.0.len(),
264            });
265        }
266        self.0.insert(index as usize, node_id);
267        Ok(())
268    }
269}
270
271impl NodeArray {
272    pub fn get(&self, index: usize) -> Option<NodeId> {
273        self.0.get(index).copied()
274    }
275
276    pub fn push(&mut self, node_id: NodeId) -> Result<(), InsertErrorKind> {
277        self.0.push(node_id);
278        Ok(())
279    }
280
281    pub fn add_at(&mut self, index: usize, node_id: NodeId) -> Result<(), InsertErrorKind> {
282        if index != self.0.len() {
283            return Err(InsertErrorKind::ArrayIndexInvalid {
284                index,
285                expected_index: self.0.len(),
286            });
287        }
288        self.0.insert(index, node_id);
289        Ok(())
290    }
291}
292
293#[cfg(test)]
294mod tests {
295    use super::*;
296
297    fn identifier(s: &str) -> Identifier {
298        s.parse().unwrap()
299    }
300
301    #[test]
302    fn test_require_map_on_uninitialized() {
303        let mut node = Node {
304            content: NodeValue::Hole,
305            extensions: Map::new(),
306        };
307
308        let map = node.require_map().expect("Should convert to map");
309        assert_eq!(map.0.len(), 0);
310
311        // Verify content was changed
312        assert!(node.as_map().is_some());
313    }
314
315    #[test]
316    fn test_require_map_on_existing_map() {
317        let mut node = Node {
318            content: NodeValue::Map(Default::default()),
319            extensions: Map::new(),
320        };
321
322        let map = node.require_map().expect("Should return existing map");
323        assert_eq!(map.0.len(), 0);
324    }
325
326    #[test]
327    fn test_require_map_on_wrong_type() {
328        let mut node = Node {
329            content: NodeValue::Primitive(PrimitiveValue::Null),
330            extensions: Map::new(),
331        };
332
333        let result = node.require_map();
334        assert_eq!(result, Err(InsertErrorKind::ExpectedMap));
335    }
336
337    #[test]
338    fn test_require_tuple_on_uninitialized() {
339        let mut node = Node {
340            content: NodeValue::Hole,
341            extensions: Map::new(),
342        };
343
344        let tuple = node.require_tuple().expect("Should convert to tuple");
345        assert_eq!(tuple.0.len(), 0);
346
347        // Verify content was changed
348        assert!(node.as_tuple().is_some());
349    }
350
351    #[test]
352    fn test_require_tuple_on_existing_tuple() {
353        let mut node = Node {
354            content: NodeValue::Tuple(Default::default()),
355            extensions: Map::new(),
356        };
357
358        let tuple = node.require_tuple().expect("Should return existing tuple");
359        assert_eq!(tuple.0.len(), 0);
360    }
361
362    #[test]
363    fn test_require_tuple_on_wrong_type() {
364        let mut node = Node {
365            content: NodeValue::Primitive(PrimitiveValue::Null),
366            extensions: Map::new(),
367        };
368
369        let result = node.require_tuple();
370        assert_eq!(result, Err(InsertErrorKind::ExpectedTuple));
371    }
372
373    #[test]
374    fn test_require_array_on_uninitialized() {
375        let mut node = Node {
376            content: NodeValue::Hole,
377            extensions: Map::new(),
378        };
379
380        let array = node.require_array().expect("Should convert to array");
381        assert_eq!(array.0.len(), 0);
382
383        // Verify content was changed
384        assert!(node.as_array().is_some());
385    }
386
387    #[test]
388    fn test_require_array_on_existing_array() {
389        let mut node = Node {
390            content: NodeValue::Array(Default::default()),
391            extensions: Map::new(),
392        };
393
394        let array = node.require_array().expect("Should return existing array");
395        assert_eq!(array.0.len(), 0);
396    }
397
398    #[test]
399    fn test_require_array_on_wrong_type() {
400        let mut node = Node {
401            content: NodeValue::Primitive(PrimitiveValue::Null),
402            extensions: Map::new(),
403        };
404
405        let result = node.require_array();
406        assert_eq!(result, Err(InsertErrorKind::ExpectedArray));
407    }
408
409    #[test]
410    fn test_node_get_extension_exists() {
411        let mut doc = EureDocument::new();
412        let root_id = doc.get_root_id();
413        let ext_identifier = identifier("test_ext");
414
415        // Add an extension
416        let ext_node_id = doc
417            .add_extension(ext_identifier.clone(), root_id)
418            .expect("Failed to add extension")
419            .node_id;
420
421        // Test get_extension on the node
422        let root_node = doc.node(root_id);
423        let result = root_node.get_extension(&ext_identifier);
424
425        assert!(result.is_some());
426        assert_eq!(result.unwrap(), ext_node_id);
427    }
428
429    #[test]
430    fn test_node_get_extension_missing() {
431        let doc = EureDocument::new();
432        let root_id = doc.get_root_id();
433        let ext_identifier = identifier("nonexistent");
434
435        // Test get_extension for a missing extension
436        let root_node = doc.node(root_id);
437        let result = root_node.get_extension(&ext_identifier);
438
439        assert!(result.is_none());
440    }
441
442    #[test]
443    fn test_node_mut_get_extension_exists() {
444        let mut doc = EureDocument::new();
445        let root_id = doc.get_root_id();
446        let ext_identifier = identifier("test_ext");
447
448        // Add an extension
449        let ext_node_id = doc
450            .add_extension(ext_identifier.clone(), root_id)
451            .expect("Failed to add extension")
452            .node_id;
453
454        // Test NodeMut::get_extension
455        let node_mut = NodeMut::new(&mut doc, root_id);
456        let result = node_mut.get_extension(&ext_identifier);
457
458        assert!(result.is_some());
459        let ext_node_mut = result.unwrap();
460        assert_eq!(ext_node_mut.node_id, ext_node_id);
461    }
462
463    #[test]
464    fn test_node_mut_get_extension_missing() {
465        let mut doc = EureDocument::new();
466        let root_id = doc.get_root_id();
467        let ext_identifier = identifier("nonexistent");
468
469        // Test NodeMut::get_extension for a missing extension
470        let node_mut = NodeMut::new(&mut doc, root_id);
471        let result = node_mut.get_extension(&ext_identifier);
472
473        assert!(result.is_none());
474    }
475
476    #[test]
477    fn test_node_mut_debug_valid_node() {
478        let mut doc = EureDocument::new();
479        let root_id = doc.get_root_id();
480
481        // Create a NodeMut with valid node_id
482        let node_mut = NodeMut::new(&mut doc, root_id);
483        let debug_output = alloc::format!("{:?}", node_mut);
484
485        // Should contain NodeMut, node_id, and delegate to Node's Debug
486        assert!(debug_output.contains("NodeMut"));
487        assert!(debug_output.contains("NodeId"));
488        assert!(debug_output.contains("Node"));
489        assert!(debug_output.contains("Hole"));
490    }
491
492    #[test]
493    fn test_node_mut_debug_invalid_node() {
494        let mut doc = EureDocument::new();
495        let invalid_id = NodeId(999999); // Invalid NodeId
496
497        // Create a NodeMut with invalid node_id
498        let node_mut = NodeMut::new(&mut doc, invalid_id);
499        let debug_output = alloc::format!("{:?}", node_mut);
500
501        // Should contain NodeMut and "<invalid>"
502        assert!(debug_output.contains("NodeMut"));
503        assert!(debug_output.contains("<invalid>"));
504    }
505}