gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1111HTML 1039Markdown 12TOML 94524 Sutichaykuna

⎇ 6ce86a9e53b741a8b58e0daa5d4bdfe80ec1f456 src/tree/taffy_tree.rs Rust · 729 siq'ikuna · 25.5 KB Ñawpa willay Pi imata llamkarqan ch'uya

Refactor/module hierarchy (#443) 628d7e1bc · Nico Burns ·

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