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}