querylizer/
deepform.rs

1// Copyright 2022 Jonathan Giddy
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashSet;
16
17use serde::{ser, Serialize, Serializer};
18
19use crate::{EncodingFn, QuerylizerError};
20
21enum State {
22    // Top-level outside any container
23    Outer,
24    // Inside a container, but no elements yet
25    InnerFirst,
26    // Inside a container after first element
27    InnerNext,
28}
29
30/// Serialize a value into an OpenAPI form body.
31pub struct DeepForm<'s, F>
32where
33    F: for<'a> EncodingFn<'a>,
34{
35    output: &'s mut String,
36    name: &'s str,
37    encoder: &'s F,
38    state: State,
39    deep: &'s HashSet<&'s str>,
40}
41
42impl<'s, F> DeepForm<'s, F>
43where
44    F: for<'a> EncodingFn<'a>,
45{
46    /// Serialize a form body into a new string to be used for web requests.
47    ///
48    /// # Example
49    ///
50    /// ```
51    /// use std::collections::HashSet;
52    /// use querylizer::{encode_www_form_urlencoded, DeepForm, DeepObject};
53    /// #[derive(serde::Serialize)]
54    /// struct A {
55    ///     a: i32,
56    ///     b: String,
57    /// }
58    /// #[derive(serde::Serialize)]
59    /// struct B {
60    ///     x: i32,
61    ///     y: A,
62    /// }
63    /// let a = A { a: 12, b: "#hello".to_owned() };
64    /// let b = B { x: 36, y: a };
65    /// let mut deep = HashSet::new();
66    /// deep.insert("y");
67    /// let s = DeepForm::to_string("value", &b, &encode_www_form_urlencoded, &deep).unwrap();
68    /// assert_eq!(s, "x=36&y[a]=12&y[b]=%23hello".to_owned());
69    /// ```
70    pub fn to_string<T>(
71        name: &str,
72        value: &T,
73        encoder: &F,
74        deep: &HashSet<&'s str>,
75    ) -> Result<String, QuerylizerError>
76    where
77        T: ?Sized + Serialize,
78    {
79        let mut output = String::new();
80        let mut serializer = DeepForm {
81            output: &mut output,
82            name,
83            encoder,
84            deep,
85            state: State::Outer,
86        };
87        value.serialize(&mut serializer)?;
88        Ok(output)
89    }
90
91    /// Append a form body onto an existing string to be used for web requests.
92    pub fn extend<T>(
93        output: &mut String,
94        name: &str,
95        value: &T,
96        encoder: &F,
97        deep: &HashSet<&'s str>,
98    ) -> Result<(), QuerylizerError>
99    where
100        T: ?Sized + Serialize,
101    {
102        let mut serializer = DeepForm {
103            output,
104            name,
105            encoder,
106            deep,
107            state: State::Outer,
108        };
109        value.serialize(&mut serializer)?;
110        Ok(())
111    }
112}
113
114impl<'a, 's, F> Serializer for &'a mut DeepForm<'s, F>
115where
116    F: for<'b> EncodingFn<'b>,
117{
118    type Ok = ();
119
120    // The error type when some error occurs during serialization.
121    type Error = QuerylizerError;
122
123    // Associated types for keeping track of additional state while serializing
124    // compound data structures like sequences and maps. In this case no
125    // additional state is required beyond what is already stored in the
126    // Serializer struct.
127    type SerializeSeq = Self;
128    type SerializeTuple = Self;
129    type SerializeTupleStruct = Self;
130    type SerializeTupleVariant = Self;
131    type SerializeMap = Self;
132    type SerializeStruct = Self;
133    type SerializeStructVariant = Self;
134
135    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
136        self.serialize_str(if v { "true" } else { "false" })
137    }
138
139    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
140        self.serialize_i32(i32::from(v))
141    }
142    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
143        self.serialize_i32(i32::from(v))
144    }
145    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
146        let mut buffer = itoa::Buffer::new();
147        self.serialize_str(buffer.format(v))
148    }
149    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
150        let mut buffer = itoa::Buffer::new();
151        self.serialize_str(buffer.format(v))
152    }
153    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
154        let mut buffer = itoa::Buffer::new();
155        self.serialize_str(buffer.format(v))
156    }
157
158    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
159        self.serialize_u32(u32::from(v))
160    }
161    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
162        self.serialize_u32(u32::from(v))
163    }
164    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
165        let mut buffer = itoa::Buffer::new();
166        self.serialize_str(buffer.format(v))
167    }
168    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
169        let mut buffer = itoa::Buffer::new();
170        self.serialize_str(buffer.format(v))
171    }
172    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
173        let mut buffer = itoa::Buffer::new();
174        self.serialize_str(buffer.format(v))
175    }
176
177    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
178        let mut buffer = dtoa::Buffer::new();
179        self.serialize_str(buffer.format(v))
180    }
181    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
182        let mut buffer = dtoa::Buffer::new();
183        self.serialize_str(buffer.format(v))
184    }
185
186    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
187        let mut buf = [0u8; 4];
188        let s = v.encode_utf8(&mut buf);
189        self.serialize_str(s)?;
190        Ok(())
191    }
192
193    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
194        if let State::Outer = self.state {
195            self.output.extend(self.encoder.call(self.name));
196            self.output.push('=');
197        }
198        self.output.extend(self.encoder.call(v));
199        Ok(())
200    }
201
202    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
203        use ser::SerializeSeq;
204        let mut seq_serializer = self.serialize_seq(Some(v.len()))?;
205        for byte in v {
206            seq_serializer.serialize_element(byte)?;
207        }
208        SerializeSeq::end(seq_serializer)?;
209        Ok(())
210    }
211
212    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
213        if let State::Outer = self.state {
214            self.serialize_str("")
215        } else {
216            Err(QuerylizerError::UnsupportedNesting)
217        }
218    }
219
220    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
221    where
222        T: ?Sized + Serialize,
223    {
224        if let State::Outer = self.state {
225            value.serialize(self)
226        } else {
227            Err(QuerylizerError::UnsupportedNesting)
228        }
229    }
230
231    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
232        if let State::Outer = self.state {
233            self.serialize_str("")
234        } else {
235            Err(QuerylizerError::UnsupportedNesting)
236        }
237    }
238
239    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
240        Err(QuerylizerError::UnsupportedNesting)
241    }
242
243    fn serialize_unit_variant(
244        self,
245        _name: &'static str,
246        _variant_index: u32,
247        _variant: &'static str,
248    ) -> Result<Self::Ok, Self::Error> {
249        if let State::Outer = self.state {
250            self.serialize_str("")
251        } else {
252            Err(QuerylizerError::UnsupportedNesting)
253        }
254    }
255
256    fn serialize_newtype_struct<T>(
257        self,
258        _name: &'static str,
259        value: &T,
260    ) -> Result<Self::Ok, Self::Error>
261    where
262        T: ?Sized + Serialize,
263    {
264        value.serialize(self)
265    }
266
267    fn serialize_newtype_variant<T>(
268        self,
269        _name: &'static str,
270        _variant_index: u32,
271        _variant: &'static str,
272        value: &T,
273    ) -> Result<Self::Ok, Self::Error>
274    where
275        T: ?Sized + Serialize,
276    {
277        value.serialize(self)
278    }
279
280    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
281        match self.state {
282            State::Outer => {
283                self.state = State::InnerFirst;
284                Ok(self)
285            }
286            _ => Err(QuerylizerError::UnsupportedNesting),
287        }
288    }
289
290    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
291        match self.state {
292            State::Outer => {
293                self.state = State::InnerFirst;
294                Ok(self)
295            }
296            _ => Err(QuerylizerError::UnsupportedNesting),
297        }
298    }
299
300    fn serialize_tuple_struct(
301        self,
302        _name: &'static str,
303        _len: usize,
304    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
305        match self.state {
306            State::Outer => {
307                self.state = State::InnerFirst;
308                Ok(self)
309            }
310            _ => Err(QuerylizerError::UnsupportedNesting),
311        }
312    }
313
314    fn serialize_tuple_variant(
315        self,
316        _name: &'static str,
317        _variant_index: u32,
318        _variant: &'static str,
319        _len: usize,
320    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
321        match self.state {
322            State::Outer => {
323                self.state = State::InnerFirst;
324                Ok(self)
325            }
326            _ => Err(QuerylizerError::UnsupportedNesting),
327        }
328    }
329
330    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
331        match self.state {
332            State::Outer => {
333                self.state = State::InnerFirst;
334                Ok(self)
335            }
336            _ => Err(QuerylizerError::UnsupportedNesting),
337        }
338    }
339
340    fn serialize_struct(
341        self,
342        _name: &'static str,
343        _len: usize,
344    ) -> Result<Self::SerializeStruct, Self::Error> {
345        match self.state {
346            State::Outer => {
347                self.state = State::InnerFirst;
348                Ok(self)
349            }
350            _ => Err(QuerylizerError::UnsupportedNesting),
351        }
352    }
353
354    fn serialize_struct_variant(
355        self,
356        _name: &'static str,
357        _variant_index: u32,
358        _variant: &'static str,
359        _len: usize,
360    ) -> Result<Self::SerializeStructVariant, Self::Error> {
361        match self.state {
362            State::Outer => {
363                self.state = State::InnerFirst;
364                Ok(self)
365            }
366            _ => Err(QuerylizerError::UnsupportedNesting),
367        }
368    }
369}
370
371macro_rules! seq_serializer {
372    ($trait:ty, $serialize:ident) => {
373        impl<'a, 's, F> $trait for &'a mut DeepForm<'s, F>
374        where
375            F: for<'b> EncodingFn<'b>,
376        {
377            type Ok = ();
378            type Error = QuerylizerError;
379
380            fn $serialize<T>(&mut self, value: &T) -> Result<(), Self::Error>
381            where
382                T: ?Sized + Serialize,
383            {
384                match self.state {
385                    State::Outer => unreachable!(),
386                    State::InnerFirst => {
387                        self.state = State::InnerNext;
388                        self.output.extend(self.encoder.call(&self.name));
389                        self.output.push('=');
390                    }
391                    State::InnerNext => {
392                        self.output.push('&');
393                        self.output.extend(self.encoder.call(&self.name));
394                        self.output.push('=');
395                    }
396                }
397                value.serialize(&mut **self)
398            }
399
400            fn end(self) -> Result<(), Self::Error> {
401                match self.state {
402                    State::Outer => unreachable!(),
403                    State::InnerFirst => Err(QuerylizerError::UnsupportedValue),
404                    State::InnerNext => {
405                        self.state = State::Outer;
406                        Ok(())
407                    }
408                }
409            }
410        }
411    };
412}
413
414seq_serializer!(ser::SerializeSeq, serialize_element);
415seq_serializer!(ser::SerializeTuple, serialize_element);
416seq_serializer!(ser::SerializeTupleStruct, serialize_field);
417seq_serializer!(ser::SerializeTupleVariant, serialize_field);
418
419impl<'a, 's, F> ser::SerializeMap for &'a mut DeepForm<'s, F>
420where
421    F: for<'b> EncodingFn<'b>,
422{
423    type Ok = ();
424    type Error = QuerylizerError;
425
426    fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
427    where
428        T: ?Sized + Serialize,
429    {
430        match self.state {
431            State::Outer => unreachable!(),
432            State::InnerFirst => {
433                self.state = State::InnerNext;
434            }
435            State::InnerNext => {
436                self.output.push('&');
437            }
438        }
439        key.serialize(&mut **self)
440    }
441
442    fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
443    where
444        T: ?Sized + Serialize,
445    {
446        match self.state {
447            State::Outer => unreachable!(),
448            _ => {
449                self.output.push('=');
450            }
451        }
452        value.serialize(&mut **self)
453    }
454
455    fn end(self) -> Result<(), Self::Error> {
456        match self.state {
457            State::Outer => unreachable!(),
458            State::InnerFirst => Err(QuerylizerError::UnsupportedValue),
459            State::InnerNext => {
460                self.state = State::Outer;
461                Ok(())
462            }
463        }
464    }
465}
466
467macro_rules! struct_serializer {
468    ($trait:ty) => {
469        impl<'a, 's, F> $trait for &'a mut DeepForm<'s, F>
470        where
471            F: for<'b> EncodingFn<'b>,
472        {
473            type Ok = ();
474            type Error = QuerylizerError;
475
476            fn serialize_field<T>(
477                &mut self,
478                key: &'static str,
479                value: &T,
480            ) -> Result<(), Self::Error>
481            where
482                T: ?Sized + Serialize,
483            {
484                if self.deep.contains(key) {
485                    match self.state {
486                        State::Outer => unreachable!(),
487                        State::InnerFirst => {
488                            self.state = State::InnerNext;
489                        }
490                        State::InnerNext => {
491                            self.output.push('&');
492                        }
493                    }
494                    crate::DeepObject::extend(self.output, key, value, self.encoder)
495                } else {
496                    match self.state {
497                        State::Outer => unreachable!(),
498                        State::InnerFirst => {
499                            self.state = State::InnerNext;
500                        }
501                        State::InnerNext => {
502                            self.output.push('&');
503                        }
504                    }
505                    key.serialize(&mut **self)?;
506                    match self.state {
507                        State::Outer => unreachable!(),
508                        _ => {
509                            self.output.push('=');
510                        }
511                    }
512                    value.serialize(&mut **self)
513                }
514            }
515
516            fn end(self) -> Result<(), Self::Error> {
517                match self.state {
518                    State::Outer => unreachable!(),
519                    State::InnerFirst => Err(QuerylizerError::UnsupportedValue),
520                    State::InnerNext => {
521                        self.state = State::Outer;
522                        Ok(())
523                    }
524                }
525            }
526        }
527    };
528}
529
530struct_serializer!(ser::SerializeStruct);
531struct_serializer!(ser::SerializeStructVariant);
532
533#[cfg(test)]
534mod tests {
535    use std::collections::HashSet;
536
537    use serde::Serialize;
538
539    use crate::{passthrough, QuerylizerError};
540
541    use super::DeepForm;
542
543    #[test]
544    fn test_bool() -> Result<(), QuerylizerError> {
545        assert_eq!(
546            DeepForm::to_string("color", &true, &passthrough, &HashSet::new())?,
547            "color=true"
548        );
549        assert_eq!(
550            DeepForm::to_string("color", &false, &passthrough, &HashSet::new())?,
551            "color=false"
552        );
553        Ok(())
554    }
555
556    #[test]
557    fn test_i8() -> Result<(), QuerylizerError> {
558        assert_eq!(
559            DeepForm::to_string("color", &-1i8, &passthrough, &HashSet::new())?,
560            "color=-1"
561        );
562        Ok(())
563    }
564
565    #[test]
566    fn test_i16() -> Result<(), QuerylizerError> {
567        assert_eq!(
568            DeepForm::to_string("color", &-1i16, &passthrough, &HashSet::new())?,
569            "color=-1"
570        );
571        Ok(())
572    }
573
574    #[test]
575    fn test_i32() -> Result<(), QuerylizerError> {
576        assert_eq!(
577            DeepForm::to_string("color", &-1i32, &passthrough, &HashSet::new())?,
578            "color=-1"
579        );
580        Ok(())
581    }
582
583    #[test]
584    fn test_i64() -> Result<(), QuerylizerError> {
585        assert_eq!(
586            DeepForm::to_string("color", &-1i64, &passthrough, &HashSet::new())?,
587            "color=-1"
588        );
589        Ok(())
590    }
591
592    #[test]
593    fn test_i128() -> Result<(), QuerylizerError> {
594        assert_eq!(
595            DeepForm::to_string("color", &-1i128, &passthrough, &HashSet::new())?,
596            "color=-1"
597        );
598        Ok(())
599    }
600
601    #[test]
602    fn test_u8() -> Result<(), QuerylizerError> {
603        assert_eq!(
604            DeepForm::to_string("color", &1u8, &passthrough, &HashSet::new())?,
605            "color=1"
606        );
607        Ok(())
608    }
609
610    #[test]
611    fn test_u16() -> Result<(), QuerylizerError> {
612        assert_eq!(
613            DeepForm::to_string("color", &1u16, &passthrough, &HashSet::new())?,
614            "color=1"
615        );
616        Ok(())
617    }
618
619    #[test]
620    fn test_u32() -> Result<(), QuerylizerError> {
621        assert_eq!(
622            DeepForm::to_string("color", &1u32, &passthrough, &HashSet::new())?,
623            "color=1"
624        );
625        Ok(())
626    }
627
628    #[test]
629    fn test_u64() -> Result<(), QuerylizerError> {
630        assert_eq!(
631            DeepForm::to_string("color", &1u64, &passthrough, &HashSet::new())?,
632            "color=1"
633        );
634        Ok(())
635    }
636
637    #[test]
638    fn test_u128() -> Result<(), QuerylizerError> {
639        assert_eq!(
640            DeepForm::to_string("color", &1u128, &passthrough, &HashSet::new())?,
641            "color=1"
642        );
643        Ok(())
644    }
645
646    #[test]
647    fn test_f32() -> Result<(), QuerylizerError> {
648        assert_eq!(
649            DeepForm::to_string("color", &0.25f32, &passthrough, &HashSet::new())?,
650            "color=0.25"
651        );
652        Ok(())
653    }
654
655    #[test]
656    fn test_f64() -> Result<(), QuerylizerError> {
657        assert_eq!(
658            DeepForm::to_string("color", &0.25f64, &passthrough, &HashSet::new())?,
659            "color=0.25"
660        );
661        Ok(())
662    }
663
664    #[test]
665    fn test_char() -> Result<(), QuerylizerError> {
666        assert_eq!(
667            DeepForm::to_string("color", &'d', &passthrough, &HashSet::new())?,
668            "color=d"
669        );
670        Ok(())
671    }
672
673    #[test]
674    fn test_str() -> Result<(), QuerylizerError> {
675        assert_eq!(
676            DeepForm::to_string("color", &"blue", &passthrough, &HashSet::new())?,
677            "color=blue"
678        );
679        Ok(())
680    }
681
682    #[test]
683    fn test_bytes() -> Result<(), QuerylizerError> {
684        assert_eq!(
685            DeepForm::to_string("color", b"blue", &passthrough, &HashSet::new())?,
686            "color=98&color=108&color=117&color=101"
687        );
688        Ok(())
689    }
690
691    #[test]
692    fn test_none() -> Result<(), QuerylizerError> {
693        assert_eq!(
694            DeepForm::to_string::<Option<u32>>(
695                "color",
696                &None,
697                &passthrough,
698                &HashSet::new()
699            )?,
700            "color="
701        );
702        Ok(())
703    }
704
705    #[test]
706    fn test_some() -> Result<(), QuerylizerError> {
707        assert_eq!(
708            DeepForm::to_string("color", &Some(1u32), &passthrough, &HashSet::new())?,
709            "color=1"
710        );
711        Ok(())
712    }
713
714    #[test]
715    fn test_unit() -> Result<(), QuerylizerError> {
716        assert_eq!(
717            DeepForm::to_string("color", &(), &passthrough, &HashSet::new())?,
718            "color="
719        );
720        Ok(())
721    }
722
723    #[test]
724    fn test_unit_struct() -> Result<(), QuerylizerError> {
725        #[derive(Serialize)]
726        struct T {}
727        assert_eq!(
728            DeepForm::to_string("color", &T {}, &passthrough, &HashSet::new()),
729            Err(QuerylizerError::UnsupportedValue)
730        );
731        Ok(())
732    }
733
734    #[test]
735    fn test_unit_variant() -> Result<(), QuerylizerError> {
736        #[derive(Serialize)]
737        enum E {
738            A,
739        }
740        assert_eq!(
741            DeepForm::to_string("color", &E::A, &passthrough, &HashSet::new())?,
742            "color="
743        );
744        Ok(())
745    }
746
747    #[test]
748    fn test_newtype_struct() -> Result<(), QuerylizerError> {
749        #[derive(Serialize)]
750        struct Metres(u32);
751        assert_eq!(
752            DeepForm::to_string("color", &Metres(5), &passthrough, &HashSet::new())?,
753            "color=5"
754        );
755        Ok(())
756    }
757
758    #[test]
759    fn test_newtype_variant() -> Result<(), QuerylizerError> {
760        #[derive(Serialize)]
761        enum E {
762            A(u32),
763        }
764        assert_eq!(
765            DeepForm::to_string("color", &E::A(5), &passthrough, &HashSet::new())?,
766            "color=5"
767        );
768        Ok(())
769    }
770
771    #[test]
772    fn test_seq() -> Result<(), QuerylizerError> {
773        let v = vec!["blue", "black", "brown"];
774        assert_eq!(
775            DeepForm::to_string("color", &v, &passthrough, &HashSet::new())?,
776            "color=blue&color=black&color=brown"
777        );
778        Ok(())
779    }
780
781    #[test]
782    fn test_tuple() -> Result<(), QuerylizerError> {
783        let t = ("blue", "black", "brown");
784        assert_eq!(
785            DeepForm::to_string("color", &t, &passthrough, &HashSet::new())?,
786            "color=blue&color=black&color=brown"
787        );
788        Ok(())
789    }
790
791    #[test]
792    fn test_tuple_struct() -> Result<(), QuerylizerError> {
793        #[derive(Serialize)]
794        struct Triple(&'static str, &'static str, &'static str);
795        let v = Triple("blue", "black", "brown");
796        assert_eq!(
797            DeepForm::to_string("color", &v, &passthrough, &HashSet::new())?,
798            "color=blue&color=black&color=brown"
799        );
800        Ok(())
801    }
802
803    #[test]
804    fn test_tuple_variant() -> Result<(), QuerylizerError> {
805        #[derive(Serialize)]
806        enum E {
807            A(u32, char),
808        }
809        assert_eq!(
810            DeepForm::to_string("color", &E::A(5, 'f'), &passthrough, &HashSet::new())?,
811            "color=5&color=f"
812        );
813        Ok(())
814    }
815
816    #[test]
817    fn test_map() -> Result<(), QuerylizerError> {
818        let mut m = std::collections::BTreeMap::new();
819        m.insert("R", 100);
820        m.insert("G", 200);
821        m.insert("B", 150);
822        assert_eq!(
823            DeepForm::to_string("color", &m, &passthrough, &HashSet::new())?,
824            "B=150&G=200&R=100"
825        );
826        Ok(())
827    }
828
829    #[test]
830    fn test_struct() {
831        #[derive(Serialize)]
832        struct Test {
833            #[serde(rename = "R")]
834            r: u32,
835            #[serde(rename = "G")]
836            g: u32,
837            #[serde(rename = "B")]
838            b: u32,
839        }
840
841        let test = Test {
842            r: 100,
843            g: 200,
844            b: 150,
845        };
846        assert_eq!(
847            DeepForm::to_string("color", &test, &passthrough, &HashSet::new()).unwrap(),
848            "R=100&G=200&B=150"
849        );
850    }
851
852    #[test]
853    fn test_struct_variant() {
854        #[derive(Serialize)]
855        struct Test {
856            #[serde(rename = "R")]
857            r: u32,
858            #[serde(rename = "G")]
859            g: u32,
860            #[serde(rename = "B")]
861            b: u32,
862        }
863        #[derive(Serialize)]
864        enum E {
865            T(Test),
866        }
867
868        let test = E::T(Test {
869            r: 100,
870            g: 200,
871            b: 150,
872        });
873        assert_eq!(
874            DeepForm::to_string("color", &test, &passthrough, &HashSet::new()).unwrap(),
875            "R=100&G=200&B=150"
876        );
877    }
878
879    #[test]
880    fn test_struct_deep() {
881        #[derive(Serialize)]
882        struct Test {
883            #[serde(rename = "R")]
884            r: u32,
885            #[serde(rename = "G")]
886            g: u32,
887            #[serde(rename = "B")]
888            b: u32,
889        }
890        #[derive(Serialize)]
891        struct Outer {
892            a: u32,
893            b: Test,
894        }
895        let outer = Outer {
896            a: 20,
897            b: Test {
898                r: 100,
899                g: 200,
900                b: 150,
901            },
902        };
903        let mut deep = HashSet::new();
904        deep.insert("b");
905        assert_eq!(
906            DeepForm::to_string("color", &outer, &passthrough, &deep).unwrap(),
907            "a=20&b[R]=100&b[G]=200&b[B]=150"
908        );
909    }
910
911    #[test]
912    fn test_unsupported_nesting() {
913        #[derive(Serialize)]
914        struct Test {
915            #[serde(rename = "R")]
916            r: u32,
917            #[serde(rename = "G")]
918            g: u32,
919            #[serde(rename = "B")]
920            b: u32,
921        }
922
923        #[derive(Serialize)]
924        struct Outer {
925            t: Test,
926        }
927        let test = Outer {
928            t: Test {
929                r: 100,
930                g: 200,
931                b: 150,
932            },
933        };
934        assert_eq!(
935            DeepForm::to_string("color", &test, &passthrough, &HashSet::new()),
936            Err(QuerylizerError::UnsupportedNesting)
937        );
938    }
939}