1use anyhow::Result;
2
3use crate::allocator::{AId, ASlice, AVec, AllocatorType, Element, HtmlAllocator, Node, ToASlice};
4
5pub enum Flat<T> {
6 None,
7 One(AId<T>),
8 Two(AId<T>, AId<T>),
9 Slice(ASlice<T>),
10}
11
12impl<T: AllocatorType> Flat<T> {
13 pub fn to_vec(self, allocator: &HtmlAllocator) -> Result<AVec<'_, T>> {
14 match self {
15 Flat::None => Ok(allocator.new_vec()),
16 Flat::One(a) => {
17 let mut v = allocator.new_vec();
18 v.push(a)?;
19 Ok(v)
20 }
21 Flat::Two(a, b) => {
22 let mut v = allocator.new_vec();
23 v.push(a)?;
24 v.push(b)?;
25 Ok(v)
26 }
27 Flat::Slice(sl) => {
28 let mut vec = allocator.new_vec();
29 for v in sl.iter_aid(allocator) {
30 vec.push(v)?;
31 }
32 Ok(vec)
33 }
34 }
35 }
36}
37
38impl<T: AllocatorType> ToASlice<T> for Flat<T> {
39 fn to_aslice(self, allocator: &HtmlAllocator) -> Result<ASlice<T>> {
40 match self {
41 Flat::None => Ok(allocator.empty_slice()),
42 Flat::One(a) => {
43 let mut v = allocator.new_vec();
44 v.push(a)?;
45 Ok(v.as_slice())
46 }
47 Flat::Two(a, b) => {
48 let mut v = allocator.new_vec();
49 v.push(a)?;
50 v.push(b)?;
51 Ok(v.as_slice())
52 }
53 Flat::Slice(sl) => Ok(sl),
54 }
55 }
56}
57
58impl<'a, T: AllocatorType> AVec<'a, T> {
59 pub fn push_flat(&mut self, flat: Flat<T>) -> Result<()> {
60 match flat {
61 Flat::None => Ok(()),
62 Flat::One(aid) => self.push(aid),
63 Flat::Two(a, b) => {
64 self.push(a)?;
65 self.push(b)?;
66 Ok(())
67 }
68 Flat::Slice(slice) => self.extend_from_slice(&slice, self.allocator()),
69 }
70 }
71}
72
73impl<'a, T: AllocatorType> ASlice<T> {
74 pub fn try_flat_map<F: Fn(AId<T>) -> Result<Flat<T>>>(
75 &self,
76 f: F,
77 capacity: Option<u32>, allocator: &'a HtmlAllocator,
79 ) -> Result<AVec<'a, T>> {
80 let cap = capacity.unwrap_or_else(|| self.len());
81 let mut v = allocator.new_vec_with_capacity(cap)?;
82 let end = self.start + self.len;
83 for i in self.start..end {
84 let id = allocator
85 .get_id(i)
86 .expect("slice should always point to allocated storage");
87 v.push_flat(f(id)?)?; }
89 Ok(v)
90 }
91}
92
93impl Element {
94 pub fn try_flat_map_body<'a, T: AllocatorType>(
95 &self,
96 f: impl Fn(AId<Node>) -> Result<Flat<Node>>,
97 allocator: &'a HtmlAllocator,
98 ) -> Result<Element> {
99 let body2 = self.body.try_flat_map(f, None, allocator)?;
100 Ok(Element {
101 meta: self.meta,
102 attr: self.attr.clone(),
103 body: body2.as_slice(),
104 })
105 }
106}