hyperloglog_rs/
serde.rs

1use crate::array_default::ArrayDefault;
2use crate::prelude::*;
3use serde::de::Visitor;
4use serde::ser::SerializeSeq;
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8impl<P: Precision + WordType<BITS>, const BITS: usize, const N: usize> Serialize
9    for HyperLogLogArray<P, BITS, N>
10{
11    #[inline(always)]
12    /// Serializes the HyperLogLog counter using the given serializer.
13    ///
14    /// This method is part of the `Serialize` trait implementation for the HyperLogLog struct,
15    /// allowing the counter to be serialized into a format supported by the serializer.
16    ///
17    /// # Arguments
18    /// * `serializer`: The serializer used to serialize the HyperLogLog counter.
19    ///
20    /// # Returns
21    /// The serialization result, indicating success or failure.
22    ///
23    /// # Example
24    /// In this example, we serialize an array of HyperLogLog counters into a JSON string.
25    /// The resulting string is then deserialized back into an array of HyperLogLog counters.
26    ///
27    /// Since we cannot implement these traits for array, we need to wrap the array in a struct,
28    /// which in this case is `HyperLogLogArray`.
29    ///
30    /// ```rust
31    /// use serde::Serialize;
32    /// use serde_json::Serializer;
33    /// use hyperloglog_rs::prelude::*;
34    ///
35    /// let mut hll_array = HyperLogLogArray::<Precision12, 6, 3>::new();
36    /// hll_array[0].insert(&1);
37    /// hll_array[1].insert(&2);
38    /// hll_array[2].insert(&3);
39    /// let mut serializer = Serializer::new(Vec::new());
40    /// let result = hll_array.serialize(&mut serializer);
41    /// assert!(result.is_ok(), "Serialization failed, error: {:?}", result.err());
42    /// let hll_array_str = String::from_utf8(serializer.into_inner()).unwrap();
43    /// let hll_array_deserialized = serde_json::from_str(&hll_array_str);
44    /// assert!(hll_array_deserialized.is_ok(), "Deserialization failed, error: {:?}", hll_array_deserialized.err());
45    /// let hll_array_deserialized = hll_array_deserialized.unwrap();
46    /// assert_eq!(hll_array, hll_array_deserialized, "Deserialized array does not match original array");
47    /// ```
48    ///
49    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
50        let mut seq = serializer.serialize_seq(Some(N))?;
51        let counters: &[HyperLogLog<P, BITS>; N] = self.as_ref();
52        for counter in counters {
53            seq.serialize_element(&counter)?;
54        }
55        seq.end()
56    }
57}
58
59impl<'de, P: Precision + WordType<BITS>, const BITS: usize, const N: usize> Deserialize<'de>
60    for HyperLogLogArray<P, BITS, N>
61{
62    #[inline(always)]
63    /// Deserializes the HyperLogLog counter using the given deserializer.
64    ///
65    /// This method is part of the `Deserialize` trait implementation for the HyperLogLog struct,
66    /// allowing the counter to be deserialized from a format supported by the deserializer.
67    ///
68    /// # Arguments
69    /// * `deserializer`: The deserializer used to deserialize the HyperLogLog counter.
70    ///
71    /// # Returns
72    /// The deserialization result, indicating success or failure.
73    ///
74    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
75        Ok(Self::from(
76            deserializer.deserialize_seq(HLLArrayVisitor::default())?,
77        ))
78    }
79}
80
81/// Struct to deserialize a vector of u32
82pub struct HLLArrayVisitor<P: Precision + WordType<BITS>, const BITS: usize, const N: usize> {
83    _precision: core::marker::PhantomData<P>,
84}
85
86impl<P: Precision + WordType<BITS>, const BITS: usize, const N: usize> HLLArrayVisitor<P, BITS, N> {
87    /// Creates a new HLLArrayVisitor
88    pub fn new() -> Self {
89        Self {
90            _precision: core::marker::PhantomData,
91        }
92    }
93}
94
95impl<P: Precision + WordType<BITS>, const BITS: usize, const N: usize> Default
96    for HLLArrayVisitor<P, BITS, N>
97{
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103/// A visitor implementation used for deserializing an array of HLL into a fixed-size array
104///
105/// This visitor is used internally by the `serde` deserialization process for the HyperLogLog struct.
106/// It converts the deserialized sequence of HLL values into a fixed-size array.
107///
108/// # Generic Parameters
109///
110/// * `'de`: Lifetime specifier for the deserialization process.
111/// * `PRECISION`: The precision parameter of the HyperLogLog counter.
112/// * `BITS`: The number of bits used for each register in the HyperLogLog counter.
113///
114///
115/// # Associated Types
116///
117/// * `Value`: The type of the resulting fixed-size array.
118///
119/// # Methods
120///
121/// ## expecting
122///
123/// Sets the error message for the expectation of an array of HLL.
124///
125/// ### Arguments
126///
127/// * `formatter`: A mutable reference to the formatter used to format the error message.
128///
129/// ### Returns
130/// A `core::fmt::Result` indicating the success or failure of the formatting operation.
131///
132/// ## visit_seq
133/// Processes the deserialized sequence and converts it into a fixed-size array of HLL values.
134///
135/// ### Arguments
136/// * `seq`: The sequence access object used to iterate over the deserialized elements.
137///
138/// ### Returns
139/// The resulting fixed-size array of u32 values, or an error if the deserialization failed.
140impl<'de, P: Precision + WordType<BITS>, const BITS: usize, const N: usize> Visitor<'de>
141    for HLLArrayVisitor<P, BITS, N>
142{
143    type Value = [HyperLogLog<P, BITS>; N];
144
145    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
146        formatter.write_str("an array of HLL")
147    }
148
149    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
150        let mut hll_array = [HyperLogLog::default(); N];
151        let mut hll_array_iter = hll_array.iter_mut();
152        while let Some(value) = seq.next_element()? {
153            if let Some(target) = hll_array_iter.next() {
154                *target = value;
155            } else {
156                return Err(serde::de::Error::invalid_length(hll_array.len(), &self));
157            }
158        }
159        Ok(hll_array)
160    }
161}
162
163impl<P: Precision + WordType<BITS>, const BITS: usize> Serialize for HyperLogLog<P, BITS> {
164    #[inline(always)]
165    /// Serializes the HyperLogLog counter using the given serializer.
166    ///
167    /// This method is part of the `Serialize` trait implementation for the HyperLogLog struct,
168    /// allowing the counter to be serialized into a format supported by the serializer.
169    ///
170    /// # Arguments
171    /// * `serializer`: The serializer used to serialize the HyperLogLog counter.
172    ///
173    /// # Returns
174    /// The serialization result, indicating success or failure.
175    ///
176    /// # Example
177    ///
178    /// ```
179    /// use serde::Serialize;
180    /// use serde_json::Serializer;
181    /// use hyperloglog_rs::prelude::*;
182    ///
183    /// let hll = HyperLogLog::<Precision12, 6>::default();
184    /// let mut serializer = Serializer::new(Vec::new());
185    /// let result = hll.serialize(&mut serializer);
186    /// assert!(result.is_ok(), "Serialization failed, error: {:?}", result.err());
187    /// ```
188    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
189        let mut seq = serializer.serialize_seq(Some(self.words.len()))?;
190        for word in self.words.iter_elements() {
191            seq.serialize_element(word)?;
192        }
193        seq.end()
194    }
195}
196
197impl<'de, P: Precision + WordType<BITS>, const BITS: usize> Deserialize<'de>
198    for HyperLogLog<P, BITS>
199{
200    #[inline(always)]
201    /// Deserializes the HyperLogLog counter using the given deserializer.
202    ///
203    /// This method is part of the `Deserialize` trait implementation for the HyperLogLog struct,
204    /// allowing the counter to be deserialized from a format supported by the deserializer.
205    ///
206    /// # Arguments
207    /// * `deserializer`: The deserializer used to deserialize the HyperLogLog counter.
208    ///
209    /// # Returns
210    /// The deserialization result, indicating success or failure.
211    ///
212    /// # Example
213    ///
214    /// ```
215    /// use serde::de::Deserialize;
216    /// use serde_json::Deserializer;
217    /// use hyperloglog_rs::prelude::*;
218    ///
219    /// let words = [0, 0, 0, 0, 5, 0, 4, 0, 0, 3, 0, 0, 0];
220    /// let words_str = "[0, 0, 0, 0, 5, 0, 4, 0, 0, 3, 0, 0, 0]";
221    /// let mut deserializer = Deserializer::from_str(words_str);
222    /// let result = HyperLogLog::<Precision6, 6>::deserialize(&mut deserializer);
223    /// assert!(result.is_ok(), "Deserialization failed, error: {:?}", result.err());
224    /// let hll = result.unwrap();
225    /// hll.get_words().iter().zip(words.iter()).for_each(|(a, b)| assert_eq!(a, b, "Deserialized words do not match, expected: {}, actual: {}", b, a));
226    /// ```
227    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
228        let words: P::Words = deserializer.deserialize_seq(WordsVisitor::<P, BITS>::default())?;
229
230        Ok(Self::from_words(&words))
231    }
232}
233
234#[derive(Default)]
235/// Struct to deserialize a vector of u32
236pub struct WordsVisitor<P: Precision + WordType<BITS>, const BITS: usize> {
237    _precision: core::marker::PhantomData<P>,
238}
239
240/// A visitor implementation used for deserializing an array of u32 into a fixed-size array.
241///
242/// This visitor is used internally by the `serde` deserialization process for the HyperLogLog struct.
243/// It converts the deserialized sequence of u32 values into a fixed-size array.
244///
245/// # Generic Parameters
246///
247/// * `'de`: Lifetime specifier for the deserialization process.
248/// * `PRECISION`: The precision parameter of the HyperLogLog counter.
249/// * `BITS`: The number of bits used for each register in the HyperLogLog counter.
250///
251/// # Associated Types
252///
253/// * `Value`: The type of the resulting fixed-size array.
254///
255/// # Methods
256///
257/// ## expecting
258///
259/// Sets the error message for the expectation of an array of u32.
260///
261/// ### Arguments
262///
263/// * `formatter`: A mutable reference to the formatter used to format the error message.
264///
265/// ### Returns
266/// A `core::fmt::Result` indicating the success or failure of the formatting operation.
267///
268/// ## visit_seq
269/// Processes the deserialized sequence and converts it into a fixed-size array of u32 values.
270///
271/// ### Arguments
272/// * `seq`: The sequence access object used to iterate over the deserialized elements.
273///
274/// ### Returns
275/// The resulting fixed-size array of u32 values, or an error if the deserialization failed.
276impl<'de, P: Precision + WordType<BITS>, const BITS: usize> Visitor<'de> for WordsVisitor<P, BITS> {
277    type Value = P::Words;
278
279    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
280        formatter.write_str("a tuple with an array of u32 and a u32 scalar")
281    }
282
283    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
284        let mut words_array = P::Words::default_array();
285        let number_of_elements = words_array.len();
286        {
287            let mut words_array_iter = words_array.iter_elements_mut();
288            while let Some(value) = seq.next_element()? {
289                if let Some(target) = words_array_iter.next() {
290                    *target = value;
291                } else {
292                    return Err(serde::de::Error::invalid_length(number_of_elements, &self));
293                }
294            }
295        }
296        Ok(words_array)
297    }
298}