sticknodes_rs/structs/
stickfigure.rs

1use core::cell::RefCell;
2
3use core2::io::Read;
4use hashbrown::HashMap;
5use petgraph::graph::NodeIndex;
6use petgraph::visit::Dfs;
7use petgraph::visit::EdgeRef;
8use petgraph::visit::VisitMap;
9use petgraph::visit::Visitable;
10use petgraph::Direction;
11use petgraph::Graph;
12extern crate alloc;
13use alloc::{format, rc::Rc, vec, vec::Vec};
14use serde::Deserialize;
15use serde::Serialize;
16
17use crate::serialization::read::read_stickfigure;
18use crate::serialization::write::write_stickfigure;
19use crate::structs::node::*;
20use crate::Color;
21use crate::LibraryError;
22use crate::Polyfill;
23use crate::StickfigureError;
24
25const NODE_LIMIT: usize = 400;
26pub const SUPPORTED_APP_VERSION: i32 = 410;
27pub const SUPPORTED_APP_BUILD: i32 = 21;
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
30#[serde(transparent)]
31pub struct DrawOrderIndex(pub i32);
32
33pub struct IWillNotAbuseUnlimitedNodes(pub bool);
34
35impl Into<DrawOrderIndex> for i32 {
36    fn into(self) -> DrawOrderIndex {
37        DrawOrderIndex(self)
38    }
39}
40
41pub(crate) struct NodeIndices {
42    draw_index: DrawOrderIndex,
43    node_index: NodeIndex,
44}
45
46#[derive(Debug, Clone)]
47pub struct Stickfigure {
48    pub version: i32,
49    pub build: i32,
50    pub scale: f32,
51    pub color: Color,
52    pub nodes: Graph<Rc<RefCell<Node>>, ()>,
53    pub polyfills: Vec<Rc<RefCell<Polyfill>>>,
54    polyfill_anchors: Vec<DrawOrderIndex>,
55    next_draw_index: DrawOrderIndex,
56    draw_index_map: HashMap<NodeIndex, DrawOrderIndex>,
57    node_index_map: HashMap<DrawOrderIndex, NodeIndex>,
58    is_node_limit_enabled: bool,
59}
60
61#[derive(Debug, Serialize, Deserialize)]
62pub struct SerializableStickfigure {
63    pub version: i32,
64    pub build: i32,
65    pub scale: f32,
66    pub color: Color,
67    pub nodes: Vec<SerializableNode>,
68    pub polyfills: Vec<Polyfill>,
69}
70
71impl Default for Stickfigure {
72    fn default() -> Self {
73        Self {
74            version: SUPPORTED_APP_VERSION,
75            build: SUPPORTED_APP_BUILD,
76            scale: 1.0,
77            color: Color::default(),
78            nodes: Graph::new(),
79            polyfills: Vec::new(),
80            next_draw_index: DrawOrderIndex(0),
81            draw_index_map: HashMap::new(),
82            node_index_map: HashMap::new(),
83            polyfill_anchors: Vec::new(),
84            is_node_limit_enabled: true,
85        }
86    }
87}
88
89/// Public Methods
90impl Stickfigure {
91    /// Creates a new, empty `Stickfigure`, set to latest version and build.
92    pub fn new() -> Self {
93        let mut stickfigure = Stickfigure::default();
94        stickfigure.add_root_node();
95
96        stickfigure
97    }
98
99    /// Creates a new, empty `Stickfigure`, set to the specified version and build.
100    pub fn from_version_and_build(version: i32, build: i32) -> Result<Self, LibraryError> {
101        if version > Stickfigure::default().version {
102            return Err(LibraryError::UnsupportedVersion(version));
103        } else if version == Stickfigure::default().version && build > Stickfigure::default().build
104        {
105            return Err(LibraryError::UnsupportedBuild(version, build));
106        }
107
108        let mut stickfigure = Stickfigure::new();
109        stickfigure.version = version;
110        stickfigure.build = build;
111        stickfigure.add_root_node();
112
113        Ok(stickfigure)
114    }
115
116    pub fn to_serializable(&self) -> SerializableStickfigure {
117        let root_node =self.get_node(DrawOrderIndex(0)).expect("Possibly an internal bug, but please check if the stickfigure you're trying to serialize has its root node draw order index set as 0. If it is, this is probably a library bug. If it is not 0, then that might be on your end :p");
118        let mut nodes = Vec::new();
119        let serializable_nodes = root_node.borrow().build_serializable_tree(
120            &self.nodes,
121            self.node_index_from_draw_order(root_node.borrow().draw_order_index),
122        );
123        let serializable_polyfills = self
124            .polyfills
125            .iter()
126            .map(|poly| poly.borrow().clone())
127            .collect();
128        nodes.push(serializable_nodes);
129        SerializableStickfigure {
130            version: self.version,
131            build: self.build,
132            scale: self.scale,
133            color: self.color,
134            nodes: nodes,
135            polyfills: serializable_polyfills,
136        }
137    }
138
139    pub fn set_is_node_limit_enabled(
140        &mut self,
141        is_enabled: bool,
142        agree: IWillNotAbuseUnlimitedNodes,
143    ) {
144        if agree.0 {
145            self.is_node_limit_enabled = is_enabled;
146        }
147    }
148
149    pub(crate) fn add_root_node(&mut self) {
150        let rc_node = Rc::new(RefCell::new(Node::new()));
151        let draw_index = DrawOrderIndex(0);
152
153        Node::update(&rc_node, |n| {
154            n.node_type = NodeType::RootNode;
155            n.draw_order_index = draw_index;
156        });
157
158        let node_index = self.nodes.add_node(Rc::clone(&rc_node));
159
160        self.remap_draw_index(node_index, draw_index);
161    }
162
163    /// Creates a new `Stickfigure` from raw bytes of a `.nodes` file.
164    pub fn from_bytes(reader: &mut impl Read) -> Result<Self, LibraryError> {
165        let stickfigure = read_stickfigure(reader)?;
166        Ok(stickfigure)
167    }
168
169    /// Get raw bytes of a `.nodes` file from an existing `Stickfigure`.
170    pub fn to_bytes(&self) -> Result<Vec<u8>, LibraryError> {
171        let mut byte_vec = Vec::new();
172
173        byte_vec.append(&mut write_stickfigure(self)?);
174
175        Ok(byte_vec)
176    }
177
178    /// Adds a new node to the stickfigure.
179    ///
180    /// The node is given a unique `DrawOrderIndex`.
181    ///
182    /// # Parameters
183    ///
184    /// * `node` - The `Node` to add to the `Stickfigure`.
185    /// * `parent_draw_index` - The `DrawOrderIndex` of the node to add this node as a child of
186    ///
187    /// # Returns
188    ///
189    /// Result of `DrawOrderIndex` of the newly added node.
190    pub fn add_node(
191        &mut self,
192        node: Node,
193        parent_draw_index: DrawOrderIndex,
194    ) -> Result<DrawOrderIndex, StickfigureError> {
195        self.check_if_can_add_node(1)?;
196
197        let rc_node = Rc::new(RefCell::new(node));
198        let draw_index = self.get_next_draw_index();
199
200        Node::update(&rc_node, |n| {
201            n.draw_order_index = draw_index;
202        });
203
204        let node_index = self.nodes.add_node(rc_node);
205
206        self.remap_draw_index(node_index, draw_index);
207
208        self.add_edge(parent_draw_index, draw_index);
209
210        Ok(draw_index)
211    }
212
213    pub fn add_node_at_index(
214        &mut self,
215        node: Node,
216        parent_draw_index: DrawOrderIndex,
217        draw_index: DrawOrderIndex,
218    ) -> Result<DrawOrderIndex, StickfigureError> {
219        let temp_draw_index = self.add_node(node, parent_draw_index)?;
220
221        self.change_draw_index(temp_draw_index, draw_index)?;
222
223        Ok(draw_index)
224    }
225
226    pub fn change_draw_index(
227        &mut self,
228        draw_index: DrawOrderIndex,
229        new_draw_index: DrawOrderIndex,
230    ) -> Result<(), StickfigureError> {
231        if draw_index == new_draw_index {
232            return Ok(());
233        }
234
235        if !self.node_index_map.contains_key(&draw_index) {
236            return Err(StickfigureError::InvalidDrawIndex(
237                draw_index.0,
238                format!("Not attempting to change any indices."),
239            ));
240        }
241
242        let node_index = self.node_index_from_draw_order(draw_index);
243
244        if self.node_index_map.contains_key(&new_draw_index) {
245            let mut affected_nodes: Vec<NodeIndices> = self
246                .draw_index_map
247                .iter()
248                .filter(|(_, &draw_index)| draw_index.0 >= new_draw_index.0)
249                .map(|(&node_index, &draw_index)| NodeIndices {
250                    node_index,
251                    draw_index,
252                })
253                .collect();
254
255            affected_nodes.sort_by_key(|node_indices| node_indices.draw_index.0);
256
257            for indices in affected_nodes.iter_mut() {
258                let draw_index_ = {
259                    let node = self.nodes.node_weight(indices.node_index).expect("This node index was retrieved from the node_index_map, so it should be valid, but apparently is not - bug in library logic");
260
261                    Node::update(&node, |n| {
262                        n.draw_order_index.0 += 1;
263                    });
264
265                    node.borrow().draw_order_index
266                };
267
268                self.draw_index_map.insert(indices.node_index, draw_index_);
269                self.node_index_map.insert(draw_index_, indices.node_index);
270            }
271        }
272
273        let node = self.nodes.node_weight(node_index).expect("Earlier in this method call the draw order index was evaluated to be valid, which means its associated node index must exist, but apparently does not - bug in library logic");
274        Node::update(&node, |n| {
275            n.draw_order_index = new_draw_index;
276        });
277
278        self.remap_draw_index(node_index, new_draw_index);
279        self.compact_draw_indices();
280
281        Ok(())
282    }
283
284    /// Gets a reference to a node.
285    ///
286    /// # Parameters
287    ///
288    /// * `draw_index` - The `DrawOrderIndex` of the node.
289    ///
290    /// # Returns
291    ///
292    /// An `Option` containing a reference to the node if it exists.
293    pub fn get_node(&self, draw_index: DrawOrderIndex) -> Option<&Rc<RefCell<Node>>> {
294        if !self.node_index_map.contains_key(&draw_index) {
295            return None;
296        }
297        let node_index = self.node_index_from_draw_order(draw_index);
298        self.nodes.node_weight(node_index)
299    }
300
301    // Gets a mutable reference to a node.
302    //
303    // # Parameters
304    //
305    // * `draw_index` - The `DrawOrderIndex` of the node.
306    //
307    // # Returns
308    //
309    // An `Option` containing a mutable reference to the node if it exists.
310    // pub fn get_node_mut(&mut self, draw_index: DrawOrderIndex) -> Option<&mut Node> {
311    //     if !self.node_index_map.contains_key(&draw_index) {
312    //         return None;
313    //     }
314    //     let node_index = self.node_index_from_draw_order(draw_index);
315    //     self.nodes.node_weight_mut(node_index)
316    // }
317
318    /// Get the `DrawOrderIndex` of the direct parent of the `Node` at the specified `DrawOrderIndex`.
319    pub fn get_parent(&self, draw_index: DrawOrderIndex) -> Option<DrawOrderIndex> {
320        let child_node_index = self.node_index_from_draw_order(draw_index);
321
322        if let Some(parent_node_index) = self
323            .nodes
324            .neighbors_directed(child_node_index, petgraph::Direction::Incoming)
325            .next()
326        {
327            let parent_draw_index = self.draw_order_from_node_index(parent_node_index);
328
329            Some(parent_draw_index)
330        } else {
331            None
332        }
333    }
334
335    /// Get a `Vec<DrawOrderIndex>` containing all `DrawOrderIndex`s of `Node`s that are direct children of the `Node` at the specified `DrawOrderIndex`.
336    pub fn get_children(&self, parent_draw_index: DrawOrderIndex) -> Vec<DrawOrderIndex> {
337        let parent_node_index = self.node_index_from_draw_order(parent_draw_index);
338
339        let child_node_indices: Vec<NodeIndex> = self
340            .nodes
341            .neighbors_directed(parent_node_index, petgraph::Direction::Outgoing)
342            .collect();
343
344        let child_draw_indices = self.draw_order_indices_from_node_indices(&child_node_indices);
345
346        child_draw_indices
347    }
348
349    pub fn get_children_recursive(&self, draw_index: DrawOrderIndex) -> Vec<DrawOrderIndex> {
350        let node_index = self.node_index_from_draw_order(draw_index);
351        let mut children = Vec::new();
352        let mut dfs = Dfs::new(&self.nodes, node_index);
353
354        while let Some(nx) = dfs.next(&self.nodes) {
355            if nx != node_index {
356                children.push(nx);
357            }
358        }
359
360        self.draw_order_indices_from_node_indices(&children)
361    }
362
363    pub fn get_parents_recursive(&self, draw_index: DrawOrderIndex) -> Vec<DrawOrderIndex> {
364        let start = self.node_index_from_draw_order(draw_index);
365        let mut ancestors = Vec::new();
366
367        // Use our own DFS stack for incoming edges
368        let mut stack = vec![start];
369        let mut visited = self.nodes.visit_map();
370
371        while let Some(node) = stack.pop() {
372            if !visited.visit(node) {
373                continue;
374            }
375
376            for neighbor in self.nodes.neighbors_directed(node, Direction::Incoming) {
377                if visited.is_visited(&neighbor) {
378                    continue;
379                }
380
381                ancestors.push(neighbor);
382                stack.push(neighbor);
383            }
384        }
385
386        self.draw_order_indices_from_node_indices(&ancestors)
387    }
388
389    pub fn get_all_node_indices(&self) -> Vec<DrawOrderIndex> {
390        let indices: Vec<NodeIndex> = self.nodes.node_indices().collect();
391
392        self.draw_order_indices_from_node_indices(&indices)
393    }
394
395    /// Gets the sibling nodes of a given node.
396    ///
397    /// Sibling nodes are nodes that share the same parent.
398    ///
399    /// # Parameters
400    ///
401    /// * `draw_index` - The `DrawOrderIndex` of the node whose siblings are to be found.
402    ///
403    /// # Returns
404    ///
405    /// A `Vec` of `DrawOrderIndex` representing the siblings of the given node.
406    pub fn get_siblings(&self, draw_index: DrawOrderIndex) -> Vec<DrawOrderIndex> {
407        let mut siblings = Vec::new();
408        let mut parents = Vec::new();
409
410        let node_index = self.node_index_from_draw_order(draw_index);
411
412        for edge in self.nodes.edges_directed(node_index, petgraph::Incoming) {
413            parents.push(edge.source());
414        }
415
416        for parent in parents {
417            for edge in self.nodes.edges_directed(parent, petgraph::Outgoing) {
418                let child = edge.target();
419                if child != node_index {
420                    siblings.push(child);
421                }
422            }
423        }
424
425        let siblings_draw_indices = self.draw_order_indices_from_node_indices(&siblings);
426
427        siblings_draw_indices
428    }
429
430    pub fn get_nodes_with_property<F>(&self, mut predicate: F) -> Vec<DrawOrderIndex>
431    where
432        F: FnMut(&Rc<RefCell<Node>>) -> bool,
433    {
434        let node_indices: Vec<NodeIndex> = self
435            .nodes
436            .node_indices()
437            .filter(|&i| {
438                if let Some(node_data) = self.nodes.node_weight(i) {
439                    predicate(node_data)
440                } else {
441                    false
442                }
443            })
444            .collect();
445
446        let draw_indices = self.draw_order_indices_from_node_indices(&node_indices);
447
448        draw_indices
449    }
450
451    pub fn update_nodes_with_property<F>(&mut self, mut predicate: F, mut updater: F)
452    where
453        F: FnMut(&Rc<RefCell<Node>>),
454    {
455        for node_index in self.nodes.node_indices() {
456            if let Some(node_data) = self.nodes.node_weight(node_index) {
457                predicate(node_data);
458                updater(node_data);
459            }
460        }
461    }
462
463    pub fn remove_node(&mut self, draw_index: DrawOrderIndex) -> Result<(), StickfigureError> {
464        if !self.node_index_map.contains_key(&draw_index) {
465            return Err(StickfigureError::InvalidDrawIndex(
466                draw_index.0,
467                format!("Cancelling node removal."),
468            ));
469        }
470        let node_index = self.node_index_from_draw_order(draw_index);
471
472        if let Some(parent_draw_index) = self.get_parent(draw_index) {
473            let child_draw_indices: Vec<DrawOrderIndex> = self.get_children(draw_index);
474
475            for child_draw_index in child_draw_indices.iter() {
476                self.add_edge(parent_draw_index, *child_draw_index);
477            }
478        }
479
480        self.nodes.remove_node(node_index);
481        self.compact_draw_indices();
482
483        Ok(())
484    }
485
486    pub fn add_polyfill(&mut self, polyfill: Polyfill) -> DrawOrderIndex {
487        let rc_polyfill = Rc::new(RefCell::new(polyfill));
488        let draw_index = { rc_polyfill.borrow().anchor_node_draw_index };
489        self.polyfill_anchors
490            .push(rc_polyfill.borrow().anchor_node_draw_index);
491        self.polyfills.push(rc_polyfill);
492        draw_index
493    }
494
495    pub fn get_polyfill(&self, draw_index: DrawOrderIndex) -> Option<Rc<RefCell<Polyfill>>> {
496        if let Some(polyfill) = self
497            .polyfills
498            .iter()
499            .find(|poly| poly.borrow().anchor_node_draw_index == draw_index)
500        {
501            Some(Rc::clone(polyfill))
502        } else {
503            None
504        }
505    }
506
507    pub fn remove_polyfill(
508        &mut self,
509        anchor_draw_order: DrawOrderIndex,
510    ) -> Result<(), StickfigureError> {
511        let rc_polyfills: Vec<Rc<RefCell<Polyfill>>> = self
512            .polyfills
513            .iter()
514            .map(|rc_poly| Rc::clone(rc_poly))
515            .filter(|polyfill| polyfill.borrow().anchor_node_draw_index != anchor_draw_order)
516            .collect();
517
518        let anchor_to_remove_index = self
519            .polyfill_anchors
520            .iter()
521            .position(|el| *el == anchor_draw_order);
522
523        match anchor_to_remove_index {
524            Some(index) => {
525                self.polyfill_anchors.remove(index);
526            },
527            None => {
528                return Err(StickfigureError::InvalidDrawIndex(anchor_draw_order.0, format!("Anchor node draw index not found in internal polyfill_anchors Vec. Likely some kind of logical error. Cancelling polyfill removal.")))
529            },
530        }
531
532        self.polyfills = rc_polyfills;
533        Ok(())
534    }
535
536    /// Returns true if all provided DrawOrderIndices exist in the node_index_map.
537    pub fn all_draw_indices_exist(&self, indices: &[DrawOrderIndex]) -> bool {
538        indices
539            .iter()
540            .all(|index| self.node_index_map.contains_key(index))
541    }
542
543    /// Returns true if provided DrawOrderIndex exists in the node_index_map.
544    pub fn draw_index_exists(&self, draw_index: DrawOrderIndex) -> bool {
545        self.node_index_map.contains_key(&draw_index)
546    }
547
548    pub fn draw_index_is_polyfill_anchor(&self, draw_index: DrawOrderIndex) -> bool {
549        self.polyfill_anchors.contains(&draw_index)
550    }
551
552    /// Returns a Vec of DrawOrderIndices that do not exist in node_index_map.
553    pub fn missing_draw_indices(&self, indices: &[DrawOrderIndex]) -> Vec<DrawOrderIndex> {
554        indices
555            .iter()
556            .filter(|index| !self.node_index_map.contains_key(*index))
557            .cloned()
558            .collect()
559    }
560}
561
562/// Private Methods
563impl Stickfigure {
564    pub(crate) fn add_node_at_unique_index(
565        &mut self,
566        node: Node,
567        parent_draw_index: DrawOrderIndex,
568        draw_index: DrawOrderIndex,
569    ) -> Result<NodeIndices, StickfigureError> {
570        if self.node_index_map.contains_key(&draw_index) {
571            return Err(StickfigureError::OccupiedDrawIndex(draw_index.0 ,format!("add_node_at_unique_index will not attempt to shift indices. This is likely being called while reading a stickfigure file. If that's the case, the file likely has duplicate draw order indices. If that's not the case or the file has all unique draw order indices, then there's a bug with the library.")).into());
572        }
573
574        let rc_node = Rc::new(RefCell::new(node));
575
576        Node::update(&rc_node, |n| {
577            n.draw_order_index = draw_index;
578        });
579
580        let node_index = self.nodes.add_node(rc_node);
581
582        self.remap_draw_index(node_index, draw_index);
583
584        self.add_edge(parent_draw_index, draw_index);
585
586        Ok(NodeIndices {
587            draw_index,
588            node_index,
589        })
590    }
591
592    pub(crate) fn add_edge(
593        &mut self,
594        parent_draw_index: DrawOrderIndex,
595        child_draw_index: DrawOrderIndex,
596    ) {
597        let parent_node_index = self.node_index_from_draw_order(parent_draw_index);
598        let child_node_index = self.node_index_from_draw_order(child_draw_index);
599
600        self.nodes.add_edge(parent_node_index, child_node_index, ());
601    }
602
603    /// Converts NodeIndex to DrawOrderIndex in O(1) time
604    pub(crate) fn draw_order_from_node_index(&self, node_index: NodeIndex) -> DrawOrderIndex {
605        self.draw_index_map
606            .get(&node_index)
607            .copied()
608            .expect("NodeIndex missing DrawOrderIndex — bug in Stickfigure logic")
609    }
610
611    pub(crate) fn draw_order_indices_from_node_indices(
612        &self,
613        node_indices: &[NodeIndex],
614    ) -> Vec<DrawOrderIndex> {
615        node_indices
616            .iter()
617            .map(|ni| self.draw_order_from_node_index(*ni))
618            .collect()
619    }
620
621    /// Converts DrawOrderIndex to NodeIndex in O(1) time
622    pub(crate) fn node_index_from_draw_order(&self, draw_index: DrawOrderIndex) -> NodeIndex {
623        self.node_index_map
624            .get(&draw_index)
625            .copied()
626            .expect("NodeIndex missing DrawOrderIndex — bug in Stickfigure logic")
627    }
628
629    pub(crate) fn node_indices_from_draw_order_indices(
630        &self,
631        draw_indices: &[DrawOrderIndex],
632    ) -> Vec<NodeIndex> {
633        draw_indices
634            .iter()
635            .map(|di| self.node_index_from_draw_order(*di))
636            .collect()
637    }
638
639    fn insert_new_indices(&mut self, node_indices: NodeIndices) {
640        if self.draw_index_map.contains_key(&node_indices.node_index)
641            || self.node_index_map.contains_key(&node_indices.draw_index)
642        {
643            panic!("Library is attempting to insert a new index pair that already exists - this is a bug with the library")
644        }
645
646        self.draw_index_map
647            .insert(node_indices.node_index, node_indices.draw_index);
648        self.node_index_map
649            .insert(node_indices.draw_index, node_indices.node_index);
650    }
651
652    fn get_next_draw_index(&mut self) -> DrawOrderIndex {
653        while self.node_index_map.contains_key(&self.next_draw_index) {
654            self.next_draw_index.0 += 1;
655        }
656
657        self.next_draw_index
658    }
659
660    fn remap_draw_index(&mut self, node_index: NodeIndex, draw_index: DrawOrderIndex) {
661        self.draw_index_map.insert(node_index, draw_index);
662        self.node_index_map.insert(draw_index, node_index);
663    }
664
665    fn compact_draw_indices(&mut self) {
666        // Get all current mappings, sorted by current draw index
667        let mut indexed_nodes: Vec<(DrawOrderIndex, NodeIndex)> = self
668            .node_index_map
669            .iter()
670            .map(|(draw_index, node_index)| (*draw_index, *node_index))
671            .collect();
672
673        indexed_nodes.sort_by_key(|(draw_index, _)| *draw_index);
674
675        // Clear existing maps
676        self.draw_index_map.clear();
677        self.node_index_map.clear();
678
679        // Reassign contiguous draw indices starting from 0
680        for (new_draw_index, (_, node_index)) in indexed_nodes.into_iter().enumerate() {
681            let new_draw_index = DrawOrderIndex(new_draw_index as i32);
682            self.remap_draw_index(node_index, new_draw_index);
683        }
684
685        // Update next_draw_index to be one past the highest used
686        self.next_draw_index = DrawOrderIndex(self.draw_index_map.len() as i32);
687    }
688
689    fn check_if_can_add_node(
690        &self,
691        number_of_nodes_being_added: usize,
692    ) -> Result<(), StickfigureError> {
693        let node_count = self.nodes.node_count();
694        if self.is_node_limit_enabled {
695            if node_count >= NODE_LIMIT {
696                return Err(StickfigureError::NodeLimitError(
697                    number_of_nodes_being_added,
698                    node_count,
699                    NODE_LIMIT,
700                ));
701            }
702        }
703        Ok(())
704    }
705}