Improve error handling for index based API
1#[cfg(not(feature = "std"))]
2use alloc::{vec, vec::Vec};
3
4use core::any::Any;
5
6use std::collections::HashMap;
7use std::ops::Drop;
8use std::sync::Mutex;
9
10use crate::geometry::Size;
11use crate::id;
12use crate::number::Number;
13use crate::result::{Cache, Layout};
14use crate::style::*;
15use crate::Error;
16
17type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>, Box<Any>>>;
18
19lazy_static! {
20 /// Global stretch instance id allocator.
21 static ref INSTANCE_ALLOCATOR: Mutex<id::Allocator> = Mutex::new(id::Allocator::new());
22}
23
24#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
25pub struct Node {
26 instance: id::Id,
27 local: id::Id,
28}
29
30pub(crate) struct Storage<T>(HashMap<Node, T>);
31
32impl<T> Storage<T> {
33 pub fn new() -> Self {
34 Storage(HashMap::new())
35 }
36
37 pub fn get(&self, node: Node) -> Result<&T, Error> {
38 match self.0.get(&node) {
39 Some(v) => Ok(v),
40 None => Err(Error::InvalidNode(node)),
41 }
42 }
43
44 pub fn get_mut(&mut self, node: Node) -> Result<&mut T, Error> {
45 match self.0.get_mut(&node) {
46 Some(v) => Ok(v),
47 None => Err(Error::InvalidNode(node)),
48 }
49 }
50
51 pub fn insert(&mut self, node: Node, value: T) -> Option<T> {
52 self.0.insert(node, value)
53 }
54}
55
56impl<T> std::ops::Index<&Node> for Storage<T> {
57 type Output = T;
58
59 fn index(&self, idx: &Node) -> &T {
60 &(self.0)[idx]
61 }
62}
63
64pub struct Stretch {
65 id: id::Id,
66 nodes: id::Allocator,
67 pub(crate) style: Storage<Style>,
68 pub(crate) parents: Storage<Vec<Node>>,
69 pub(crate) children: Storage<Vec<Node>>,
70 pub(crate) measure: Storage<Option<MeasureFunc>>,
71 pub(crate) layout: Storage<Layout>,
72 pub(crate) layout_cache: Storage<Option<Cache>>,
73 pub(crate) is_dirty: Storage<bool>,
74}
75
76impl Stretch {
77 pub fn new() -> Self {
78 Stretch {
79 id: INSTANCE_ALLOCATOR.lock().unwrap().allocate(),
80 nodes: id::Allocator::new(),
81 style: Storage::new(),
82 parents: Storage::new(),
83 children: Storage::new(),
84 measure: Storage::new(),
85 layout: Storage::new(),
86 layout_cache: Storage::new(),
87 is_dirty: Storage::new(),
88 }
89 }
90
91 fn allocate_node(&mut self) -> Node {
92 let local = self.nodes.allocate();
93 Node { instance: self.id, local }
94 }
95
96 pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> Node {
97 let node = self.allocate_node();
98
99 self.style.insert(node, style);
100 self.parents.insert(node, Vec::with_capacity(1));
101 self.children.insert(node, Vec::with_capacity(0));
102 self.measure.insert(node, Some(measure));
103 self.layout.insert(node, Layout::new());
104 self.layout_cache.insert(node, None);
105 self.is_dirty.insert(node, true);
106
107 node
108 }
109
110 pub fn new_node(&mut self, style: Style, children: Vec<Node>) -> Result<Node, Error> {
111 let node = self.allocate_node();
112
113 for child in &children {
114 self.parents.get_mut(*child)?.push(node);
115 }
116
117 self.style.insert(node, style);
118 self.parents.insert(node, Vec::with_capacity(1));
119 self.children.insert(node, children);
120 self.measure.insert(node, None);
121 self.layout.insert(node, Layout::new());
122 self.layout_cache.insert(node, None);
123 self.is_dirty.insert(node, true);
124
125 Ok(node)
126 }
127
128 pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), Error> {
129 *self.measure.get_mut(node)? = measure;
130 self.mark_dirty(node)?;
131 Ok(())
132 }
133
134 pub fn add_child(&mut self, node: Node, child: Node) {
135 // child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
136 // self.0.borrow_mut().children.push(Rc::clone(&child.0));
137 // self.mark_dirty();
138
139 unimplemented!()
140 }
141
142 pub fn set_children(&mut self, node: Node, children: Vec<Node>) {
143 // for child in &self.0.borrow().children {
144 // let position =
145 // child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
146 // child.borrow_mut().parents.remove(position);
147 // }
148
149 // self.0.borrow_mut().children = Vec::with_capacity(children.len());
150
151 // for child in children {
152 // child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
153 // self.0.borrow_mut().children.push(Rc::clone(&child.0));
154 // }
155
156 // self.mark_dirty();
157
158 unimplemented!()
159 }
160
161 pub fn remove_child(&mut self, node: Node, child: Node) -> Node {
162 // self.remove_child_at_index({
163 // let parent = self.0.borrow();
164 // parent.children.iter().position(|x| Rc::ptr_eq(&x, &child.0)).unwrap()
165 // })
166
167 unimplemented!()
168 }
169
170 pub fn remove_child_at_index(&mut self, node: Node, index: usize) -> Node {
171 // let child = {
172 // let mut parent = self.0.borrow_mut();
173 // let child = parent.children.remove(index);
174 // let position =
175 // child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
176 // child.borrow_mut().parents.remove(position);
177 // child
178 // };
179
180 // self.mark_dirty();
181 // Node(child)
182
183 unimplemented!()
184 }
185
186 pub fn replace_child_at_index(&mut self, node: Node, index: usize, child: Node) -> Node {
187 // child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
188 // let old_child = std::mem::replace(&mut self.0.borrow_mut().children[index], Rc::clone(&child.0));
189
190 // let position =
191 // old_child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
192 // old_child.borrow_mut().parents.remove(position);
193
194 // self.mark_dirty();
195
196 // Node(old_child)
197
198 unimplemented!()
199 }
200
201 pub fn children(&self, node: Node) -> Result<Vec<Node>, Error> {
202 self.children.get(node).map(Clone::clone)
203 }
204
205 pub fn child_count(&self, node: Node) -> Result<usize, Error> {
206 self.children.get(node).map(Vec::len)
207 }
208
209 pub fn set_style(&mut self, node: Node, style: Style) {
210 // self.0.borrow_mut().style = style;
211 // self.mark_dirty();
212
213 unimplemented!()
214 }
215
216 pub fn style(&self, node: Node) -> Result<&Style, Error> {
217 self.style.get(node)
218 }
219
220 pub fn layout(&self, node: Node) -> Result<&Layout, Error> {
221 self.layout.get(node)
222 }
223
224 pub fn mark_dirty(&mut self, node: Node) -> Result<(), Error> {
225 // let mut node = self.0.borrow_mut();
226 // node.layout_cache = None;
227 // node.is_dirty = true;
228
229 // for parent in &node.parents {
230 // if let Some(parent) = parent.upgrade() {
231 // Node(parent).mark_dirty();
232 // }
233 // }
234
235 unimplemented!()
236 }
237
238 pub fn dirty(&self, node: Node) -> Result<bool, Error> {
239 self.is_dirty.get(node).map(|v| *v)
240 }
241
242 pub fn compute_layout(&mut self, node: Node, size: Size<Number>) -> Result<(), Error> {
243 match self.layout.get(node) {
244 Ok(_) => self.compute(node, size).map_err(|err| Error::Measure(err)),
245 _ => Err(Error::InvalidNode(node)),
246 }
247 }
248}
249
250impl Drop for Stretch {
251 fn drop(&mut self) {
252 INSTANCE_ALLOCATOR.lock().unwrap().free(&[self.id]);
253 }
254}