gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5334Rust 85Markdown 12TOML 91813 Sutichaykuna

⎇ fb07aa8a6de7135b57ec4a440b86cfe10ffcdbd0 src/node.rs Rust · 711 siq'ikuna · 25.0 KB Ñawpa willay Pi imata llamkarqan ch'uya

Return iterator for children for `LayoutTree` (#260) af3bc5340 · George Atkinson ·

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