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
89impl Stickfigure {
91 pub fn new() -> Self {
93 let mut stickfigure = Stickfigure::default();
94 stickfigure.add_root_node();
95
96 stickfigure
97 }
98
99 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 pub fn from_bytes(reader: &mut impl Read) -> Result<Self, LibraryError> {
165 let stickfigure = read_stickfigure(reader)?;
166 Ok(stickfigure)
167 }
168
169 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 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 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 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 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 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 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 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 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 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
562impl 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 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 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 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 self.draw_index_map.clear();
677 self.node_index_map.clear();
678
679 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 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}