Skip to main content

io_msgraph/v1/
query.rs

1//! Turn a `Serialize` struct into OData URL query pairs.
2//!
3//! A minimal `no_std` serde serializer that flattens a flat struct of
4//! scalars, options and sequences into `(key, value)` string pairs ready
5//! for `url`'s `query_pairs_mut().extend_pairs(...)`. Keys come from the
6//! struct field names, so a params struct renaming its fields to the
7//! OData system query options (`$top`, `$select`, `$filter`, ...) yields
8//! the Graph query keys for free; `None` and empty sequences produce
9//! nothing, and a sequence produces one repeated-key pair per element.
10
11use core::fmt;
12
13use alloc::{
14    string::{String, ToString},
15    vec::Vec,
16};
17
18use serde::{
19    Serialize, Serializer,
20    ser::{Error as SerError, Impossible, SerializeSeq, SerializeStruct},
21};
22
23/// Serialize `value` into a list of URL query `(key, value)` pairs.
24pub fn to_query_pairs<T>(value: &T) -> Vec<(String, String)>
25where
26    T: Serialize + ?Sized,
27{
28    value.serialize(QuerySerializer).unwrap_or_default()
29}
30
31/// Error raised when a value cannot be flattened into query pairs.
32#[derive(Debug)]
33pub struct MsgraphQueryError(String);
34
35impl fmt::Display for MsgraphQueryError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.write_str(&self.0)
38    }
39}
40
41impl core::error::Error for MsgraphQueryError {}
42
43impl SerError for MsgraphQueryError {
44    fn custom<T: fmt::Display>(msg: T) -> Self {
45        Self(msg.to_string())
46    }
47}
48
49fn unsupported() -> MsgraphQueryError {
50    MsgraphQueryError(String::from(
51        "query parameters must be a flat struct of scalars and sequences",
52    ))
53}
54
55/// Top-level serializer: only a struct maps to query pairs.
56struct QuerySerializer;
57
58impl Serializer for QuerySerializer {
59    type Ok = Vec<(String, String)>;
60    type Error = MsgraphQueryError;
61    type SerializeSeq = Impossible<Self::Ok, Self::Error>;
62    type SerializeTuple = Impossible<Self::Ok, Self::Error>;
63    type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
64    type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
65    type SerializeMap = Impossible<Self::Ok, Self::Error>;
66    type SerializeStruct = StructQuery;
67    type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
68
69    fn serialize_struct(
70        self,
71        _name: &'static str,
72        len: usize,
73    ) -> Result<Self::SerializeStruct, Self::Error> {
74        Ok(StructQuery {
75            pairs: Vec::with_capacity(len),
76        })
77    }
78
79    fn serialize_newtype_struct<T>(
80        self,
81        _name: &'static str,
82        value: &T,
83    ) -> Result<Self::Ok, Self::Error>
84    where
85        T: Serialize + ?Sized,
86    {
87        value.serialize(self)
88    }
89
90    fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
91        Err(unsupported())
92    }
93    fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
94        Err(unsupported())
95    }
96    fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
97        Err(unsupported())
98    }
99    fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
100        Err(unsupported())
101    }
102    fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
103        Err(unsupported())
104    }
105    fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
106        Err(unsupported())
107    }
108    fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
109        Err(unsupported())
110    }
111    fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
112        Err(unsupported())
113    }
114    fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
115        Err(unsupported())
116    }
117    fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
118        Err(unsupported())
119    }
120    fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
121        Err(unsupported())
122    }
123    fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
124        Err(unsupported())
125    }
126    fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
127        Err(unsupported())
128    }
129    fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
130        Err(unsupported())
131    }
132    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
133        Err(unsupported())
134    }
135    fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
136    where
137        T: Serialize + ?Sized,
138    {
139        Err(unsupported())
140    }
141    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
142        Err(unsupported())
143    }
144    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
145        Err(unsupported())
146    }
147    fn serialize_unit_variant(
148        self,
149        _: &'static str,
150        _: u32,
151        _: &'static str,
152    ) -> Result<Self::Ok, Self::Error> {
153        Err(unsupported())
154    }
155    fn serialize_newtype_variant<T>(
156        self,
157        _: &'static str,
158        _: u32,
159        _: &'static str,
160        _: &T,
161    ) -> Result<Self::Ok, Self::Error>
162    where
163        T: Serialize + ?Sized,
164    {
165        Err(unsupported())
166    }
167    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
168        Err(unsupported())
169    }
170    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
171        Err(unsupported())
172    }
173    fn serialize_tuple_struct(
174        self,
175        _: &'static str,
176        _: usize,
177    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
178        Err(unsupported())
179    }
180    fn serialize_tuple_variant(
181        self,
182        _: &'static str,
183        _: u32,
184        _: &'static str,
185        _: usize,
186    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
187        Err(unsupported())
188    }
189    fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
190        Err(unsupported())
191    }
192    fn serialize_struct_variant(
193        self,
194        _: &'static str,
195        _: u32,
196        _: &'static str,
197        _: usize,
198    ) -> Result<Self::SerializeStructVariant, Self::Error> {
199        Err(unsupported())
200    }
201}
202
203/// Collects one field at a time into query pairs.
204struct StructQuery {
205    pairs: Vec<(String, String)>,
206}
207
208impl SerializeStruct for StructQuery {
209    type Ok = Vec<(String, String)>;
210    type Error = MsgraphQueryError;
211
212    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
213    where
214        T: Serialize + ?Sized,
215    {
216        value.serialize(FieldQuery {
217            key,
218            pairs: &mut self.pairs,
219        })
220    }
221
222    fn end(self) -> Result<Self::Ok, Self::Error> {
223        Ok(self.pairs)
224    }
225}
226
227/// Serializes a single field value under a fixed key, pushing one pair
228/// per scalar and one per sequence element (skipping `None`).
229struct FieldQuery<'a> {
230    key: &'static str,
231    pairs: &'a mut Vec<(String, String)>,
232}
233
234impl FieldQuery<'_> {
235    fn push(self, value: String) -> Result<(), MsgraphQueryError> {
236        self.pairs.push((self.key.to_string(), value));
237        Ok(())
238    }
239}
240
241impl<'a> Serializer for FieldQuery<'a> {
242    type Ok = ();
243    type Error = MsgraphQueryError;
244    type SerializeSeq = SeqQuery<'a>;
245    type SerializeTuple = Impossible<(), MsgraphQueryError>;
246    type SerializeTupleStruct = Impossible<(), MsgraphQueryError>;
247    type SerializeTupleVariant = Impossible<(), MsgraphQueryError>;
248    type SerializeMap = Impossible<(), MsgraphQueryError>;
249    type SerializeStruct = Impossible<(), MsgraphQueryError>;
250    type SerializeStructVariant = Impossible<(), MsgraphQueryError>;
251
252    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
253        self.push(v.to_string())
254    }
255    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
256        self.push(v.to_string())
257    }
258    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
259        self.push(v.to_string())
260    }
261    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
262        self.push(v.to_string())
263    }
264    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
265        self.push(v.to_string())
266    }
267    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
268        self.push(v.to_string())
269    }
270    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
271        self.push(v.to_string())
272    }
273    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
274        self.push(v.to_string())
275    }
276    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
277        self.push(v.to_string())
278    }
279    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
280        self.push(v.to_string())
281    }
282    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
283        self.push(v.to_string())
284    }
285    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
286        self.push(v.to_string())
287    }
288    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
289        self.push(v.to_string())
290    }
291    fn serialize_unit_variant(
292        self,
293        _: &'static str,
294        _: u32,
295        variant: &'static str,
296    ) -> Result<Self::Ok, Self::Error> {
297        self.push(variant.to_string())
298    }
299    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
300        Ok(())
301    }
302    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
303    where
304        T: Serialize + ?Sized,
305    {
306        value.serialize(self)
307    }
308    fn serialize_newtype_struct<T>(
309        self,
310        _: &'static str,
311        value: &T,
312    ) -> Result<Self::Ok, Self::Error>
313    where
314        T: Serialize + ?Sized,
315    {
316        value.serialize(self)
317    }
318    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
319        Ok(SeqQuery {
320            key: self.key,
321            pairs: self.pairs,
322        })
323    }
324
325    fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
326        Err(unsupported())
327    }
328    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
329        Err(unsupported())
330    }
331    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
332        Err(unsupported())
333    }
334    fn serialize_newtype_variant<T>(
335        self,
336        _: &'static str,
337        _: u32,
338        _: &'static str,
339        _: &T,
340    ) -> Result<Self::Ok, Self::Error>
341    where
342        T: Serialize + ?Sized,
343    {
344        Err(unsupported())
345    }
346    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
347        Err(unsupported())
348    }
349    fn serialize_tuple_struct(
350        self,
351        _: &'static str,
352        _: usize,
353    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
354        Err(unsupported())
355    }
356    fn serialize_tuple_variant(
357        self,
358        _: &'static str,
359        _: u32,
360        _: &'static str,
361        _: usize,
362    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
363        Err(unsupported())
364    }
365    fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
366        Err(unsupported())
367    }
368    fn serialize_struct(
369        self,
370        _: &'static str,
371        _: usize,
372    ) -> Result<Self::SerializeStruct, Self::Error> {
373        Err(unsupported())
374    }
375    fn serialize_struct_variant(
376        self,
377        _: &'static str,
378        _: u32,
379        _: &'static str,
380        _: usize,
381    ) -> Result<Self::SerializeStructVariant, Self::Error> {
382        Err(unsupported())
383    }
384}
385
386/// Serializes each sequence element as a repeated-key pair.
387struct SeqQuery<'a> {
388    key: &'static str,
389    pairs: &'a mut Vec<(String, String)>,
390}
391
392impl SerializeSeq for SeqQuery<'_> {
393    type Ok = ();
394    type Error = MsgraphQueryError;
395
396    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
397    where
398        T: Serialize + ?Sized,
399    {
400        value.serialize(FieldQuery {
401            key: self.key,
402            pairs: self.pairs,
403        })
404    }
405
406    fn end(self) -> Result<Self::Ok, Self::Error> {
407        Ok(())
408    }
409}