tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 501HTML 254C 19JavaScript 81414 Definitions

⎇ 832e2da45631009be13279a06c30f09962db0688 src/node.rs Rust · 745 lines · 27.4 KB History Who touched what raw

Cleanup `new_with_children()` uses (#194) 832e2da45 · Andreas Weibye ·

1//! UI [`Node`] types and related data structures.
2//!
3//! Layouts are composed of multiple nodes, which live in a forest-like data structure.
4use crate::error;
5use crate::forest::Forest;
6use crate::geometry::Size;
7use crate::layout::Layout;
8use crate::style::FlexboxLayout;
9#[cfg(any(feature = "std", feature = "alloc"))]
10use crate::sys::Box;
11use crate::sys::{new_map_with_capacity, ChildrenVec, Map, Vec};
12use core::sync::atomic::{AtomicUsize, Ordering};
13
14/// Internal node id.
15pub(crate) type NodeId = usize;
16
17/// The identifier of a [`Node`]
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
19#[cfg_attr(not(any(feature = "std", feature = "alloc")), derive(hash32_derive::Hash32))]
20pub(crate) struct Id(usize);
21
22/// An bump-allocator index that tracks how many [`Nodes`](Node) have been allocated in a [`Taffy`].
23pub(crate) struct Allocator {
24    /// The last reserved [`NodeId`]
25    last_id: AtomicUsize,
26}
27
28impl Allocator {
29    /// Creates a fresh [`Allocator`]
30    #[must_use]
31    pub const fn new() -> Self {
32        Self { last_id: AtomicUsize::new(0) }
33    }
34
35    /// Allocates space for one more [`Node`]
36    pub fn allocate(&self) -> Id {
37        Id(self.last_id.fetch_add(1, Ordering::Relaxed))
38    }
39}
40
41/// A function type that can be used in a [`MeasureFunc`]
42///
43/// This trait is automatically implemented for all types (including closures) that define a function with the appropriate type signature.
44pub trait Measurable: Send + Sync + Fn(Size<Option<f32>>) -> Size<f32> {}
45
46impl<F: Send + Sync + Fn(Size<Option<f32>>) -> Size<f32>> Measurable for F {}
47
48/// A function that can be used to compute the intrinsic size of a node
49pub enum MeasureFunc {
50    /// Stores an unboxed function
51    Raw(fn(Size<Option<f32>>) -> Size<f32>),
52    /// Stores a boxed function
53    #[cfg(any(feature = "std", feature = "alloc"))]
54    Boxed(Box<dyn Measurable>),
55}
56
57/// Global taffy instance id allocator.
58static INSTANCE_ALLOCATOR: Allocator = Allocator::new();
59
60/// An [`Id`]-containing identifier
61#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
62#[cfg_attr(not(any(feature = "std", feature = "alloc")), derive(hash32_derive::Hash32))]
63pub struct Node {
64    /// The id of the forest that this node lives with
65    instance: Id,
66    /// The identifier of this particular node within the tree
67    local: Id,
68}
69
70/// A forest of UI [`Nodes`](`Node`), suitable for UI layout
71pub struct Taffy {
72    /// The ID of the root node
73    id: Id,
74    /// A monotonically-increasing index that tracks the [`Id`] of the next node
75    allocator: Allocator,
76    /// A map from Node -> NodeId
77    nodes_to_ids: Map<Node, NodeId>,
78    /// A map from NodeId -> Node
79    ids_to_nodes: Map<NodeId, Node>,
80    /// An efficient data structure that stores the node trees
81    forest: Forest,
82}
83
84impl Default for Taffy {
85    fn default() -> Self {
86        Self::with_capacity(16)
87    }
88}
89
90impl Taffy {
91    /// Creates a new [`Taffy`]
92    ///
93    /// The default capacity of a [`Taffy`] is 16 nodes.
94    #[must_use]
95    pub fn new() -> Self {
96        Default::default()
97    }
98
99    /// Creates a new [`Taffy`] that can store `capacity` nodes before reallocation
100    pub fn with_capacity(capacity: usize) -> Self {
101        Self {
102            id: INSTANCE_ALLOCATOR.allocate(),
103            allocator: Allocator::new(),
104            nodes_to_ids: new_map_with_capacity(capacity),
105            ids_to_nodes: new_map_with_capacity(capacity),
106            forest: Forest::with_capacity(capacity),
107        }
108    }
109
110    /// Allocates memory for a new node, and returns a matching generated [`Node`]
111    fn allocate_node(&mut self) -> Node {
112        let local = self.allocator.allocate();
113        Node { instance: self.id, local }
114    }
115
116    /// Stores a new node in the tree
117    fn add_node(&mut self, node: Node, id: NodeId) {
118        let _ = self.nodes_to_ids.insert(node, id);
119        let _ = self.ids_to_nodes.insert(id, node);
120    }
121
122    /// Returns the `NodeId` of the provided node within the forest
123    fn find_node(&self, node: Node) -> Result<NodeId, error::InvalidNode> {
124        match self.nodes_to_ids.get(&node) {
125            Some(id) => Ok(*id),
126            None => Err(error::InvalidNode(node)),
127        }
128    }
129
130    /// Creates and adds a new leaf node
131    pub fn new_leaf(&mut self, layout: FlexboxLayout) -> Result<Node, error::InvalidNode> {
132        let node = self.allocate_node();
133        let id = self.forest.new_leaf(layout);
134        self.add_node(node, id);
135        Ok(node)
136    }
137
138    /// Creates and adds a new leaf node with a supplied [`MeasureFunc`]
139    pub fn new_leaf_with_measure(
140        &mut self,
141        layout: FlexboxLayout,
142        measure: MeasureFunc,
143    ) -> Result<Node, error::InvalidNode> {
144        let node = self.allocate_node();
145        let id = self.forest.new_leaf_with_measure(layout, measure);
146        self.add_node(node, id);
147        Ok(node)
148    }
149
150    /// Creates and adds a new node, which may have any number of `children`
151    pub fn new_with_children(&mut self, layout: FlexboxLayout, children: &[Node]) -> Result<Node, error::InvalidNode> {
152        let node = self.allocate_node();
153        let children = children
154            .iter()
155            .map(|child| self.find_node(*child))
156            .collect::<Result<ChildrenVec<_>, error::InvalidNode>>()?;
157        let id = self.forest.new_with_children(layout, children);
158        self.add_node(node, id);
159        Ok(node)
160    }
161
162    /// Removes all nodes
163    ///
164    /// All associated [`Id`] will be rendered invalid.
165    pub fn clear(&mut self) {
166        self.nodes_to_ids.clear();
167        self.ids_to_nodes.clear();
168        self.forest.clear();
169    }
170
171    /// Remove a specific [`Node`] from the tree
172    ///
173    /// Its [`Id`] is marked as invalid. Returns the id of the node removed.
174    pub fn remove(&mut self, node: Node) -> Result<usize, error::InvalidNode> {
175        let id = self.find_node(node)?;
176
177        self.nodes_to_ids.remove(&node);
178        self.ids_to_nodes.remove(&id);
179
180        if let Some(new_id) = self.forest.swap_remove(id) {
181            let new = self.ids_to_nodes.remove(&new_id).unwrap();
182            let _ = self.nodes_to_ids.insert(new, id);
183            let _ = self.ids_to_nodes.insert(id, new);
184        }
185
186        Ok(id)
187    }
188
189    /// Sets the [`MeasureFunc`] of the associated node
190    pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), error::InvalidNode> {
191        let id = self.find_node(node)?;
192        self.forest.nodes[id].measure = measure;
193        self.forest.mark_dirty(id);
194        Ok(())
195    }
196
197    /// Adds a `child` [`Node`] under the supplied `parent`
198    pub fn add_child(&mut self, parent: Node, child: Node) -> Result<(), error::InvalidNode> {
199        let node_id = self.find_node(parent)?;
200        let child_id = self.find_node(child)?;
201
202        self.forest.add_child(node_id, child_id);
203        Ok(())
204    }
205
206    /// Directly sets the `children` of the supplied `parent`
207    pub fn set_children(&mut self, parent: Node, children: &[Node]) -> Result<(), error::InvalidNode> {
208        let node_id = self.find_node(parent)?;
209        let children_id = children.iter().map(|child| self.find_node(*child)).collect::<Result<ChildrenVec<_>, _>>()?;
210
211        // Remove node as parent from all its current children.
212        for child in &self.forest.children[node_id] {
213            self.forest.parents[*child].retain(|p| *p != node_id);
214        }
215
216        // Build up relation node <-> child
217        for child in &children_id {
218            self.forest.parents[*child].push(node_id);
219        }
220        self.forest.children[node_id] = children_id;
221
222        self.forest.mark_dirty(node_id);
223        Ok(())
224    }
225
226    /// Removes the `child` of the parent `node`
227    ///
228    /// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
229    pub fn remove_child(&mut self, parent: Node, child: Node) -> Result<Node, error::InvalidNode> {
230        let node_id = self.find_node(parent)?;
231        let child_id = self.find_node(child)?;
232
233        let prev_id = self.forest.remove_child(node_id, child_id);
234        Ok(self.ids_to_nodes[&prev_id])
235    }
236
237    /// Removes the child at the given `index` from the `parent`
238    ///
239    /// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
240    pub fn remove_child_at_index(&mut self, parent: Node, child_index: usize) -> Result<Node, error::InvalidChild> {
241        let node_id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;
242
243        let child_count = self.forest.children[node_id].len();
244        if child_index >= child_count {
245            return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
246        }
247
248        let prev_id = self.forest.remove_child_at_index(node_id, child_index);
249        Ok(self.ids_to_nodes[&prev_id])
250    }
251
252    /// Replaces the child at the given `child_index` from the `parent` node with the new `child` node
253    ///
254    /// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
255    pub fn replace_child_at_index(
256        &mut self,
257        parent: Node,
258        child_index: usize,
259        new_child: Node,
260    ) -> Result<Node, error::InvalidChild> {
261        let node_id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;
262        let child_id = self.find_node(new_child).map_err(|e| error::InvalidChild::InvalidChildNode(e.0))?;
263
264        let child_count = self.forest.children[node_id].len();
265        if child_index >= child_count {
266            return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
267        }
268
269        self.forest.parents[child_id].push(node_id);
270        let old_child = core::mem::replace(&mut self.forest.children[node_id][child_index], child_id);
271        self.forest.parents[old_child].retain(|p| *p != node_id);
272
273        self.forest.mark_dirty(node_id);
274
275        Ok(self.ids_to_nodes[&old_child])
276    }
277
278    /// Returns the child [`Node`] of the parent `node` at the provided `child_index`
279    pub fn child_at_index(&self, parent: Node, child_index: usize) -> Result<Node, error::InvalidChild> {
280        let id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;
281
282        let child_count = self.forest.children[id].len();
283        if child_index >= child_count {
284            return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
285        }
286
287        Ok(self.ids_to_nodes[&self.forest.children[id][child_index]])
288    }
289
290    /// Returns the number of children of the `parent` [`Node`]
291    pub fn child_count(&self, parent: Node) -> Result<usize, error::InvalidNode> {
292        let id = self.find_node(parent)?;
293        Ok(self.forest.children[id].len())
294    }
295
296    /// Returns a list of children that belong to the [`Parent`]
297    pub fn children(&self, parent: Node) -> Result<Vec<Node>, error::InvalidNode> {
298        let id = self.find_node(parent)?;
299        Ok(self.forest.children[id].iter().map(|child| self.ids_to_nodes[child]).collect())
300    }
301
302    /// Sets the [`Style`] of the provided `node`
303    pub fn set_style(&mut self, node: Node, style: FlexboxLayout) -> Result<(), error::InvalidNode> {
304        let id = self.find_node(node)?;
305        self.forest.nodes[id].style = style;
306        self.forest.mark_dirty(id);
307        Ok(())
308    }
309
310    /// Gets the [`Style`] of the provided `node`
311    pub fn style(&self, node: Node) -> Result<&FlexboxLayout, error::InvalidNode> {
312        let id = self.find_node(node)?;
313        Ok(&self.forest.nodes[id].style)
314    }
315
316    /// Return this node layout relative to its parent
317    pub fn layout(&self, node: Node) -> Result<&Layout, error::InvalidNode> {
318        let id = self.find_node(node)?;
319        Ok(&self.forest.nodes[id].layout)
320    }
321
322    /// Marks the layout computation of this node and its children as outdated
323    pub fn mark_dirty(&mut self, node: Node) -> Result<(), error::InvalidNode> {
324        let id = self.find_node(node)?;
325        self.forest.mark_dirty(id);
326        Ok(())
327    }
328
329    /// Indicates whether the layout of this node (and its children) need to be recomputed
330    pub fn dirty(&self, node: Node) -> Result<bool, error::InvalidNode> {
331        let id = self.find_node(node)?;
332        Ok(self.forest.nodes[id].is_dirty)
333    }
334
335    /// Updates the stored layout of the provided `node` and its children
336    pub fn compute_layout(&mut self, node: Node, size: Size<Option<f32>>) -> Result<(), error::InvalidNode> {
337        let id = self.find_node(node)?;
338        self.forest.compute_layout(id, size);
339        Ok(())
340    }
341}
342
343#[cfg(test)]
344mod tests {
345    use super::*;
346    use crate::{
347        style::{Dimension, Display, FlexDirection},
348        sys,
349    };
350
351    #[test]
352    fn new_should_allocate_default_capacity() {
353        const DEFAULT_CAPACITY: usize = 16; // This is the capacity defined in the `impl Default`
354        let taffy = Taffy::new();
355
356        assert!(taffy.nodes_to_ids.capacity() >= DEFAULT_CAPACITY);
357        assert!(taffy.ids_to_nodes.capacity() >= DEFAULT_CAPACITY);
358        assert!(taffy.forest.children.capacity() >= DEFAULT_CAPACITY);
359        assert!(taffy.forest.parents.capacity() >= DEFAULT_CAPACITY);
360        assert!(taffy.forest.nodes.capacity() >= DEFAULT_CAPACITY);
361    }
362
363    #[test]
364    fn test_with_capacity() {
365        const CAPACITY: usize = 8;
366        let taffy = Taffy::with_capacity(CAPACITY);
367
368        assert!(taffy.nodes_to_ids.capacity() >= CAPACITY);
369        assert!(taffy.ids_to_nodes.capacity() >= CAPACITY);
370        assert!(taffy.forest.children.capacity() >= CAPACITY);
371        assert!(taffy.forest.parents.capacity() >= CAPACITY);
372        assert!(taffy.forest.nodes.capacity() >= CAPACITY);
373    }
374
375    #[test]
376    fn add_node() {
377        let mut taffy = Taffy::new();
378        let node = taffy.allocate_node();
379        let id = taffy.forest.new_leaf(FlexboxLayout::default());
380
381        // Should not contain nodes
382        assert!(!taffy.nodes_to_ids.contains_key(&node));
383        assert!(!taffy.ids_to_nodes.contains_key(&id));
384
385        taffy.add_node(node, id);
386
387        // Should contain nodes
388        assert!(taffy.nodes_to_ids.contains_key(&node));
389        assert!(taffy.ids_to_nodes.contains_key(&id));
390    }
391
392    #[test]
393    fn find_node() {
394        let mut taffy = Taffy::new();
395
396        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
397        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
398        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
399
400        // Should find the nodes
401        assert!(if let Ok(node_id) = taffy.find_node(node) { node_id == node.local.0 } else { false });
402        assert!(if let Ok(node_id) = taffy.find_node(child0) { node_id == child0.local.0 } else { false });
403        assert!(if let Ok(node_id) = taffy.find_node(child1) { node_id == child1.local.0 } else { false });
404
405        let _ = taffy.remove(node);
406        let _ = taffy.remove(child0);
407        let _ = taffy.remove(child1);
408
409        // Should not find the nodes
410        assert!(taffy.find_node(node).is_err());
411        assert!(taffy.find_node(child0).is_err());
412        assert!(taffy.find_node(child1).is_err());
413    }
414
415    #[test]
416    fn test_new_leaf() {
417        let mut taffy = Taffy::new();
418
419        let res = taffy.new_leaf(FlexboxLayout::default());
420        assert!(res.is_ok());
421        let node = res.unwrap();
422
423        // node should be in the taffy tree and have no children
424        assert!(taffy.find_node(node).is_ok());
425        assert!(taffy.child_count(node).unwrap() == 0);
426    }
427
428    #[test]
429    fn new_leaf_with_measure() {
430        let mut taffy = Taffy::new();
431
432        let res = taffy.new_leaf_with_measure(FlexboxLayout::default(), MeasureFunc::Raw(|_| Size::ZERO));
433        assert!(res.is_ok());
434        let node = res.unwrap();
435
436        // node should be in the taffy tree and have no children
437        assert!(taffy.find_node(node).is_ok());
438        assert!(taffy.child_count(node).unwrap() == 0);
439    }
440
441    /// Test that new_with_children works as expected
442    #[test]
443    fn test_new_with_children() {
444        let mut taffy = Taffy::new();
445        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
446        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
447        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
448
449        // node should have two children
450        assert_eq!(taffy.child_count(node).unwrap(), 2);
451        assert_eq!(taffy.children(node).unwrap()[0], child0);
452        assert_eq!(taffy.children(node).unwrap()[1], child1);
453    }
454
455    #[test]
456    fn clear_should_clear_nodes() {
457        let mut taffy = Taffy::new();
458        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
459        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
460        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
461
462        // Nodes should be present
463        assert!(taffy.find_node(node).is_ok());
464        assert!(taffy.find_node(child0).is_ok());
465        assert!(taffy.find_node(child1).is_ok());
466
467        taffy.clear();
468
469        // nodes should not be present
470        assert!(taffy.find_node(node).is_err());
471        assert!(taffy.find_node(child0).is_err());
472        assert!(taffy.find_node(child1).is_err());
473    }
474
475    #[test]
476    fn remove_node_should_remove() {
477        let mut taffy = Taffy::new();
478
479        let node = taffy.new_leaf(FlexboxLayout::default()).unwrap();
480
481        // node should exist
482        assert!(taffy.find_node(node).is_ok());
483
484        let _ = taffy.remove(node).unwrap();
485
486        // node should no longer exist
487        assert!(taffy.find_node(node).is_err());
488    }
489
490    #[test]
491    fn remove_node_should_detach_herarchy() {
492        let mut taffy = Taffy::new();
493
494        // Build a linear tree layout: <0> <- <1> <- <2>
495        let node2 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
496        let node1 = taffy.new_with_children(FlexboxLayout::default(), &[node2]).unwrap();
497        let node0 = taffy.new_with_children(FlexboxLayout::default(), &[node1]).unwrap();
498
499        // Node1 should exist
500        assert!(taffy.find_node(node1).is_ok());
501
502        // Both node0 and node1 should have 1 child nodes
503        assert_eq!(taffy.children(node0).unwrap().as_slice(), &[node1]);
504        assert_eq!(taffy.children(node1).unwrap().as_slice(), &[node2]);
505
506        // Disconnect the tree: <0> <2>
507        let _ = taffy.remove(node1).unwrap();
508
509        // Node1 should no longer exist
510        assert!(taffy.find_node(node1).is_err());
511
512        // Both remaining nodes should have no child nodes
513        assert!(taffy.children(node0).unwrap().is_empty());
514        assert!(taffy.children(node2).unwrap().is_empty());
515    }
516
517    #[test]
518    fn remove_last_node() {
519        let mut taffy = Taffy::new();
520
521        let parent = taffy.new_leaf(FlexboxLayout::default()).unwrap();
522        let child = taffy.new_leaf(FlexboxLayout::default()).unwrap();
523        taffy.add_child(parent, child).unwrap();
524
525        taffy.remove(child).unwrap();
526        taffy.remove(parent).unwrap();
527    }
528
529    #[test]
530    fn set_measure() {
531        let mut taffy = Taffy::new();
532        let node = taffy
533            .new_leaf_with_measure(FlexboxLayout::default(), MeasureFunc::Raw(|_| Size { width: 200.0, height: 200.0 }))
534            .unwrap();
535        taffy.compute_layout(node, Size::undefined()).unwrap();
536        assert_eq!(taffy.layout(node).unwrap().size.width, 200.0);
537
538        taffy.set_measure(node, Some(MeasureFunc::Raw(|_| Size { width: 100.0, height: 100.0 }))).unwrap();
539        taffy.compute_layout(node, Size::undefined()).unwrap();
540        assert_eq!(taffy.layout(node).unwrap().size.width, 100.0);
541    }
542
543    /// Test that adding `add_child()` works
544    #[test]
545    fn add_child() {
546        let mut taffy = Taffy::new();
547        let node = taffy.new_leaf(FlexboxLayout::default()).unwrap();
548        assert_eq!(taffy.child_count(node).unwrap(), 0);
549
550        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
551        taffy.add_child(node, child0).unwrap();
552        assert_eq!(taffy.child_count(node).unwrap(), 1);
553
554        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
555        taffy.add_child(node, child1).unwrap();
556        assert_eq!(taffy.child_count(node).unwrap(), 2);
557    }
558
559    #[test]
560    fn set_children() {
561        let mut taffy = Taffy::new();
562
563        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
564        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
565        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
566
567        assert_eq!(taffy.child_count(node).unwrap(), 2);
568        assert_eq!(taffy.children(node).unwrap()[0], child0);
569        assert_eq!(taffy.children(node).unwrap()[1], child1);
570
571        let child2 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
572        let child3 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
573        taffy.set_children(node, &[child2, child3]).unwrap();
574
575        assert_eq!(taffy.child_count(node).unwrap(), 2);
576        assert_eq!(taffy.children(node).unwrap()[0], child2);
577        assert_eq!(taffy.children(node).unwrap()[1], child3);
578    }
579
580    /// Test that removing a child works
581    #[test]
582    fn remove_child() {
583        let mut taffy = Taffy::new();
584        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
585        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
586        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
587
588        assert_eq!(taffy.child_count(node).unwrap(), 2);
589
590        taffy.remove_child(node, child0).unwrap();
591        assert_eq!(taffy.child_count(node).unwrap(), 1);
592        assert_eq!(taffy.children(node).unwrap()[0], child1);
593
594        taffy.remove_child(node, child1).unwrap();
595        assert_eq!(taffy.child_count(node).unwrap(), 0);
596    }
597
598    #[test]
599    fn remove_child_at_index() {
600        let mut taffy = Taffy::new();
601        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
602        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
603        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
604
605        assert_eq!(taffy.child_count(node).unwrap(), 2);
606
607        taffy.remove_child_at_index(node, 0).unwrap();
608        assert_eq!(taffy.child_count(node).unwrap(), 1);
609        assert_eq!(taffy.children(node).unwrap()[0], child1);
610
611        taffy.remove_child_at_index(node, 0).unwrap();
612        assert_eq!(taffy.child_count(node).unwrap(), 0);
613    }
614
615    #[test]
616    fn replace_child_at_index() {
617        let mut taffy = Taffy::new();
618
619        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
620        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
621
622        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0]).unwrap();
623        assert_eq!(taffy.child_count(node).unwrap(), 1);
624        assert_eq!(taffy.children(node).unwrap()[0], child0);
625
626        taffy.replace_child_at_index(node, 0, child1).unwrap();
627        assert_eq!(taffy.child_count(node).unwrap(), 1);
628        assert_eq!(taffy.children(node).unwrap()[0], child1);
629    }
630    #[test]
631    fn test_child_at_index() {
632        let mut taffy = Taffy::new();
633        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
634        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
635        let child2 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
636        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1, child2]).unwrap();
637
638        assert!(if let Ok(result) = taffy.child_at_index(node, 0) { result == child0 } else { false });
639        assert!(if let Ok(result) = taffy.child_at_index(node, 1) { result == child1 } else { false });
640        assert!(if let Ok(result) = taffy.child_at_index(node, 2) { result == child2 } else { false });
641    }
642    #[test]
643    fn test_child_count() {
644        let mut taffy = Taffy::new();
645        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
646        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
647        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
648
649        assert!(if let Ok(count) = taffy.child_count(node) { count == 2 } else { false });
650        assert!(if let Ok(count) = taffy.child_count(child0) { count == 0 } else { false });
651        assert!(if let Ok(count) = taffy.child_count(child1) { count == 0 } else { false });
652    }
653    #[test]
654    fn test_children() {
655        let mut taffy = Taffy::new();
656        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
657        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
658        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
659
660        let mut children: sys::Vec<Node> = sys::Vec::new();
661        children.push(child0);
662        children.push(child1);
663
664        let children_result = taffy.children(node).unwrap();
665        assert_eq!(children_result, children);
666
667        assert!(taffy.children(child0).unwrap().len() == 0);
668    }
669    #[test]
670    fn test_set_style() {
671        let mut taffy = Taffy::new();
672
673        let node = taffy.new_leaf(FlexboxLayout::default()).unwrap();
674        assert_eq!(taffy.style(node).unwrap().display, Display::Flex);
675
676        taffy.set_style(node, FlexboxLayout { display: Display::None, ..FlexboxLayout::default() }).unwrap();
677        assert_eq!(taffy.style(node).unwrap().display, Display::None);
678    }
679    #[test]
680    fn test_style() {
681        let mut taffy = Taffy::new();
682
683        let style =
684            FlexboxLayout { display: Display::None, flex_direction: FlexDirection::RowReverse, ..Default::default() };
685
686        let node = taffy.new_leaf(style).unwrap();
687
688        let res = taffy.style(node);
689        assert!(res.is_ok());
690        assert!(res.unwrap() == &style);
691    }
692    #[test]
693    fn test_layout() {
694        let mut taffy = Taffy::new();
695        let node = taffy.new_leaf(FlexboxLayout::default()).unwrap();
696
697        // TODO: Improve this test?
698        let res = taffy.layout(node);
699        assert!(res.is_ok());
700    }
701
702    #[test]
703    fn test_mark_dirty() {
704        let mut taffy = Taffy::new();
705        let child0 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
706        let child1 = taffy.new_leaf(FlexboxLayout::default()).unwrap();
707        let node = taffy.new_with_children(FlexboxLayout::default(), &[child0, child1]).unwrap();
708
709        taffy.compute_layout(node, Size::undefined()).unwrap();
710
711        assert_eq!(taffy.dirty(child0).unwrap(), false);
712        assert_eq!(taffy.dirty(child1).unwrap(), false);
713        assert_eq!(taffy.dirty(node).unwrap(), false);
714
715        taffy.mark_dirty(node).unwrap();
716        assert_eq!(taffy.dirty(child0).unwrap(), false);
717        assert_eq!(taffy.dirty(child1).unwrap(), false);
718        assert_eq!(taffy.dirty(node).unwrap(), true);
719
720        taffy.compute_layout(node, Size::undefined()).unwrap();
721        taffy.mark_dirty(child0).unwrap();
722        assert_eq!(taffy.dirty(child0).unwrap(), true);
723        assert_eq!(taffy.dirty(child1).unwrap(), false);
724        assert_eq!(taffy.dirty(node).unwrap(), true);
725    }
726
727    #[test]
728    fn compute_layout_should_produce_valid_result() {
729        let mut taffy = Taffy::new();
730        let node_result = taffy.new_leaf(FlexboxLayout {
731            size: Size { width: Dimension::Points(10f32), height: Dimension::Points(10f32) },
732            ..Default::default()
733        });
734        assert!(node_result.is_ok());
735        let node = node_result.unwrap();
736        let layout_result = taffy.compute_layout(node, Size { width: Some(100.), height: Some(100.) });
737        assert!(layout_result.is_ok());
738    }
739
740    #[test]
741    fn measure_func_is_send_and_sync() {
742        fn is_send_and_sync<T: Send + Sync>() {}
743        is_send_and_sync::<MeasureFunc>();
744    }
745}