cookie_factory/
multi.rs

1//! serializers working on a list of elements (vectors, iterators, etc)
2use crate::internal::{SerializeFn, WriteContext};
3use crate::lib::std::io::Write;
4
5/// Applies an iterator of serializers of the same type
6///
7/// ```rust
8/// use cookie_factory::{gen, multi::all, combinator::string};
9///
10/// let mut buf = [0u8; 100];
11///
12/// let data = vec!["abcd", "efgh", "ijkl"];
13/// {
14///   let (buf, pos) = gen(all(data.iter().map(string)), &mut buf[..]).unwrap();
15///   assert_eq!(pos, 12);
16///   assert_eq!(buf.len(), 100 - 12);
17/// }
18///
19/// assert_eq!(&buf[..12], &b"abcdefghijkl"[..]);
20/// ```
21pub fn all<G, W: Write, It>(values: It) -> impl SerializeFn<W>
22where
23    G: SerializeFn<W>,
24    It: Clone + Iterator<Item = G>,
25{
26    move |mut out: WriteContext<W>| {
27        let it = values.clone();
28
29        for v in it {
30            out = v(out)?;
31        }
32
33        Ok(out)
34    }
35}
36
37/// Applies an iterator of serializers of the same type with a separator between each serializer
38///
39/// ```rust
40/// use cookie_factory::{gen, multi::separated_list, combinator::string};
41///
42/// let mut buf = [0u8; 100];
43///
44/// let data = vec!["abcd", "efgh", "ijkl"];
45/// {
46///   let (buf, pos) = gen(separated_list(string(","), data.iter().map(string)), &mut buf[..]).unwrap();
47///   assert_eq!(pos, 14);
48///   assert_eq!(buf.len(), 100 - 14);
49/// }
50///
51/// assert_eq!(&buf[..14], &b"abcd,efgh,ijkl"[..]);
52/// ```
53pub fn separated_list<F, G, W: Write, It>(sep: F, values: It) -> impl SerializeFn<W>
54where
55    F: SerializeFn<W>,
56    G: SerializeFn<W>,
57    It: Clone + Iterator<Item = G>,
58{
59    move |mut out: WriteContext<W>| {
60        let mut it = values.clone();
61
62        match it.next() {
63            None => return Ok(out),
64            Some(first) => {
65                out = first(out)?;
66            }
67        }
68
69        for v in it {
70            out = sep(out).and_then(v)?;
71        }
72
73        Ok(out)
74    }
75}
76
77/// Applies a generator over an iterator of values, and applies the serializers generated
78///
79/// ```rust
80/// use cookie_factory::{gen, multi::many_ref, combinator::string};
81///
82/// let mut buf = [0u8; 100];
83///
84/// let data = vec!["abcd", "efgh", "ijkl"];
85/// {
86///   let (buf, pos) = gen(many_ref(&data, string), &mut buf[..]).unwrap();
87///   assert_eq!(pos, 12);
88///   assert_eq!(buf.len(), 100 - 12);
89/// }
90///
91/// assert_eq!(&buf[..12], &b"abcdefghijkl"[..]);
92/// ```
93pub fn many_ref<E, It, I, F, G, O: Write>(items: I, generator: F) -> impl SerializeFn<O>
94where
95    It: Iterator<Item = E> + Clone,
96    I: IntoIterator<Item = E, IntoIter = It>,
97    F: Fn(E) -> G,
98    G: SerializeFn<O>,
99{
100    let items = items.into_iter();
101    move |mut out: WriteContext<O>| {
102        for item in items.clone() {
103            out = generator(item)(out)?;
104        }
105        Ok(out)
106    }
107}