use crate::utils::{Length, opt_packing_factor};
use crate::{Arc, Error, Leaf, List, PackedLeaf, Tree, UpdateMap, Value};
use smallvec::{SmallVec, smallvec};
use tree_hash::Hash256;
use typenum::Unsigned;
pub fn repeat_list<T, N, U>(elem: T, n: usize) -> Result<List<T, N, U>, Error>
where
T: Value,
N: Unsigned,
U: UpdateMap<T>,
{
if n == 0 {
return Ok(List::empty());
}
let packing_factor = opt_packing_factor::<T>();
let tree_depth = List::<T, N, U>::depth();
let mut layer: SmallVec<[_; 2]> = if let Some(packing_factor) = packing_factor {
let repeat_count = n / packing_factor;
let lonely_count = n % packing_factor;
let repeat_leaf = Arc::new(Tree::PackedLeaf(PackedLeaf::repeat(
elem.clone(),
packing_factor,
)));
let lonely_leaf = Arc::new(Tree::PackedLeaf(PackedLeaf::repeat(elem, lonely_count)));
match (repeat_count, lonely_count) {
(0, 0) => unreachable!("n != 0"),
(_, 0) => smallvec![(repeat_leaf, repeat_count)],
(0, _) => smallvec![(lonely_leaf, 1)],
(_, _) => {
smallvec![(repeat_leaf, repeat_count), (lonely_leaf, 1)]
}
}
} else {
smallvec![(Arc::new(Tree::Leaf(Leaf::new(elem))), n)]
};
for depth in 0..tree_depth {
let new_layer = match &layer[..] {
[(repeat_leaf, 1)] => {
smallvec![(
Tree::node(repeat_leaf.clone(), Tree::zero(depth), Hash256::ZERO),
1,
)]
}
[(repeat_leaf, repeat_count)] if repeat_count.is_multiple_of(2) => {
smallvec![(
Tree::node(repeat_leaf.clone(), repeat_leaf.clone(), Hash256::ZERO),
repeat_count / 2,
)]
}
[(repeat_leaf, repeat_count)] => {
smallvec![
(
Tree::node(repeat_leaf.clone(), repeat_leaf.clone(), Hash256::ZERO),
repeat_count / 2,
),
(
Tree::node(repeat_leaf.clone(), Tree::zero(depth), Hash256::ZERO),
1,
),
]
}
[(repeat_leaf, 1), (lonely_leaf, 1)] => {
smallvec![(
Tree::node(repeat_leaf.clone(), lonely_leaf.clone(), Hash256::ZERO),
1,
)]
}
[(repeat_leaf, repeat_count), (lonely_leaf, 1)] => {
if repeat_count.is_multiple_of(2) {
smallvec![
(
Tree::node(repeat_leaf.clone(), repeat_leaf.clone(), Hash256::ZERO),
repeat_count / 2,
),
(
Tree::node(lonely_leaf.clone(), Tree::zero(depth), Hash256::ZERO),
1,
),
]
} else {
smallvec![
(
Tree::node(repeat_leaf.clone(), repeat_leaf.clone(), Hash256::ZERO),
repeat_count / 2,
),
(
Tree::node(repeat_leaf.clone(), lonely_leaf.clone(), Hash256::ZERO),
1,
),
]
}
}
_ => unreachable!("not possible"),
};
drop(std::mem::replace(&mut layer, new_layer));
}
let (root, count) = layer.pop().ok_or(Error::BuilderStackEmptyFinalize)?;
if !layer.is_empty() || count != 1 {
return Err(Error::BuilderStackLeftover);
}
Ok(List::from_parts(root, tree_depth, Length(n)))
}