tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

⎇ 07a154db4c0fb4f714f397062dd2dc1dbf407470 src/node.rs Rust · 703 líneas · 24.7 KB Historia Quién tocó qué crudo

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