1// As each benchmark suite is compiled as a seperate crate and uses different helpers, we end up with a bunch
2// of false positives for this lint. So let's just disable it for this code.
3#![allow(dead_code)]
4
5pub mod taffy_helpers;
6pub use taffy_helpers::TaffyTreeBuilder;
7
8#[cfg(feature = "yoga")]
9pub mod yoga_helpers;
10#[cfg(feature = "yoga")]
11pub use yoga_helpers::YogaTreeBuilder;
12
13use rand::distributions::uniform::SampleRange;
14use rand::{Rng, SeedableRng};
15use rand_chacha::ChaCha8Rng;
16use taffy::style::Style as TaffyStyle;
17
18pub const STANDARD_RNG_SEED: u64 = 12345;
19
20pub trait GenStyle<Style: Default> {
21 fn create_leaf_style(&mut self, rng: &mut impl Rng) -> Style;
22 fn create_container_style(&mut self, rng: &mut impl Rng) -> Style;
23 fn create_root_style(&mut self, _rng: &mut impl Rng) -> Style {
24 Default::default()
25 }
26}
27
28pub struct FixedStyleGenerator(pub TaffyStyle);
29impl GenStyle<TaffyStyle> for FixedStyleGenerator {
30 fn create_leaf_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle {
31 self.0.clone()
32 }
33 fn create_container_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle {
34 self.0.clone()
35 }
36}
37
38pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized {
39 type Tree;
40 type Node: Clone;
41
42 fn with_rng(rng: R, style_generator: G) -> Self;
43
44 fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize;
45 fn create_leaf_node(&mut self) -> Self::Node;
46 fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node;
47 fn set_root_children(&mut self, children: &[Self::Node]);
48 fn total_node_count(&mut self) -> usize;
49 fn into_tree_and_root(self) -> (Self::Tree, Self::Node);
50
51 fn build_n_leaf_nodes(&mut self, n: usize) -> Vec<Self::Node> {
52 (0..n).map(|_| self.create_leaf_node()).collect()
53 }
54
55 /// A helper function to recursively construct a deep tree
56 fn build_deep_tree(&mut self, max_nodes: u32, branching_factor: u32) -> Vec<Self::Node> {
57 if max_nodes <= branching_factor {
58 // Build leaf nodes
59 return (0..max_nodes).map(|_| self.create_leaf_node()).collect();
60 }
61
62 // Add another layer to the tree
63 // Each child gets an equal amount of the remaining nodes
64 (0..branching_factor)
65 .map(|_| {
66 let max_nodes = (max_nodes - branching_factor) / branching_factor;
67 let children = self.build_deep_tree(max_nodes, branching_factor);
68 self.create_container_node(&children)
69 })
70 .collect()
71 }
72
73 /// A helper function to recursively construct a deep tree
74 fn build_super_deep_hierarchy(mut self, depth: u32, nodes_per_level: u32) -> (Self::Tree, Self::Node) {
75 let mut children = Vec::with_capacity(nodes_per_level as usize);
76 for _ in 0..depth {
77 let node_with_children = self.create_container_node(&children);
78
79 children.clear();
80 children.push(node_with_children);
81 for _ in 0..(nodes_per_level - 1) {
82 children.push(self.create_leaf_node())
83 }
84 }
85 self.set_root_children(&children);
86 self.into_tree_and_root()
87 }
88
89 /// A tree with a higher depth for a more realistic scenario
90 fn build_deep_hierarchy(mut self, node_count: u32, branching_factor: u32) -> (Self::Tree, Self::Node) {
91 let children = self.build_deep_tree(node_count, branching_factor);
92 self.set_root_children(&children);
93 self.into_tree_and_root()
94 }
95
96 /// A tree with many children that have shallow depth
97 fn build_flat_hierarchy(mut self, target_node_count: u32) -> (Self::Tree, Self::Node) {
98 let mut children = Vec::new();
99
100 while self.total_node_count() < target_node_count as usize {
101 let count = self.random_usize(1..=4);
102 let sub_children = self.build_n_leaf_nodes(count);
103 let node = self.create_container_node(&sub_children);
104 children.push(node);
105 }
106
107 self.set_root_children(&children);
108 self.into_tree_and_root()
109 }
110}
111
112pub trait BuildTreeExt<G: GenStyle<TaffyStyle>>: BuildTree<ChaCha8Rng, G> {
113 fn with_seed(seed: u64, style_generator: G) -> Self
114 where
115 Self: Sized,
116 {
117 let rng = ChaCha8Rng::seed_from_u64(seed);
118 Self::with_rng(rng, style_generator)
119 }
120
121 fn new(style_generator: G) -> Self
122 where
123 Self: Sized,
124 {
125 Self::with_seed(STANDARD_RNG_SEED, style_generator)
126 }
127}