tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

⎇ 2e0d1bd2f08d3e477e564acfbed30c9caa2e0440 src/node.rs Rust · 614 líneas · 22.2 KB Historia Quién tocó qué crudo

Run Clippy CI on the entire workspace (#234) 2e0d1bd2f · TimJentzsch ·

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