kv_derive_impl/
producer.rs

1use std::iter;
2
3use crate::into_vec::IntoVec;
4
5/// Responsible for producing the key-value entries based on its value.
6///
7/// May produce none, one or many entries, depending on a specific type.
8pub trait Producer<T> {
9    type Iter: Iterator<Item = (String, String)>;
10
11    fn produce(self, key: &'static str, value: T) -> Self::Iter;
12}
13
14/// Scalar producer.
15///
16/// Produces exactly one key-value pair.
17#[derive(Copy, Clone)]
18pub struct ScalarProducer;
19
20impl<V: ToString> Producer<V> for ScalarProducer {
21    type Iter = iter::Once<(String, String)>;
22
23    #[inline]
24    fn produce(self, key: &'static str, value: V) -> Self::Iter {
25        iter::once((key.to_string(), value.to_string()))
26    }
27}
28
29#[derive(Copy, Clone)]
30pub struct WrappedProducer<P, F>(pub P, pub F);
31
32impl<V1, V2, P: Producer<V2>, F: Fn(V1) -> V2> Producer<V1> for WrappedProducer<P, F> {
33    type Iter = P::Iter;
34
35    #[inline]
36    fn produce(self, key: &'static str, value: V1) -> Self::Iter {
37        self.0.produce(key, self.1(value))
38    }
39}
40
41/// Optional scaler producer.
42///
43/// Produces none or one key-value pair.
44#[derive(Copy, Clone)]
45pub struct OptionProducer<P>(pub P);
46
47impl<V, P: Producer<V>> Producer<Option<V>> for OptionProducer<P> {
48    type Iter = iter::FlatMap<
49        iter::Zip<iter::Zip<std::option::IntoIter<V>, iter::Once<&'static str>>, iter::Once<P>>,
50        P::Iter,
51        fn(((V, &'static str), P)) -> P::Iter,
52    >;
53
54    #[inline]
55    fn produce(self, key: &'static str, value: Option<V>) -> Self::Iter {
56        value
57            .into_iter()
58            .zip(iter::once(key))
59            .zip(iter::once(self.0))
60            .flat_map(|((value, key), producer)| producer.produce(key, value))
61    }
62}
63
64/// Collection producer.
65///
66/// Produces as many key-value pairs as the number of the collection elements.
67#[derive(Copy, Clone)]
68pub struct CollectionProducer<P>(pub P);
69
70impl<V, P: Producer<V> + Copy + Clone> Producer<Vec<V>> for CollectionProducer<P> {
71    type Iter = iter::FlatMap<
72        iter::Zip<iter::Zip<iter::Repeat<&'static str>, std::vec::IntoIter<V>>, iter::Repeat<P>>,
73        <P as Producer<V>>::Iter,
74        fn(((&'static str, V), P)) -> <P as Producer<V>>::Iter,
75    >;
76
77    #[inline]
78    fn produce(self, key: &'static str, values: Vec<V>) -> Self::Iter {
79        iter::repeat(key)
80            .zip(values.into_iter())
81            .zip(iter::repeat(self.0))
82            .into_iter()
83            .flat_map(|((key, value), producer)| producer.produce(key, value))
84    }
85}
86
87/// Simple flattening producer.
88///
89/// Forwards all the key-value pairs from the inner structure.
90#[derive(Copy, Clone)]
91pub struct FlatteningProducer;
92
93impl<T: IntoVec> Producer<T> for FlatteningProducer {
94    type Iter = Box<dyn Iterator<Item = (String, String)>>;
95
96    #[inline]
97    fn produce(self, _key: &'static str, value: T) -> Self::Iter {
98        value.into_iter()
99    }
100}
101
102/// Prefixed flattening producer.
103///
104/// Forwards all the key-value pairs from the inner structure,
105/// but additionally prepends the keys with the prefix.
106#[derive(Copy, Clone)]
107pub struct PrefixedFlatteningProducer(pub &'static str);
108
109impl<V: IntoVec> Producer<V> for PrefixedFlatteningProducer {
110    type Iter = Box<dyn Iterator<Item = (String, String)>>;
111
112    #[inline]
113    fn produce(self, _key: &'static str, value: V) -> Self::Iter {
114        Box::new(
115            value
116                .into_iter()
117                .map(move |(key, value)| (format!("{}{}", self.0, key), value)),
118        )
119    }
120}