1use percent_encoding::{AsciiSet, CONTROLS};
2use serde::{ser, Serialize};
3
4use crate::error::{IntoHttpError, UrlError};
5
6pub fn construct_url(
18 base_url: &str,
19 endpoint: &str,
20 params: &impl Serialize,
21 query: &impl Serialize,
22) -> Result<String, IntoHttpError> {
23 let url = to_string(base_url, endpoint, params)?;
25
26 let query = serde_urlencoded::to_string(query)?;
28
29 let url = if query.is_empty() {
31 url
32 } else {
33 format!("{url}?{query}")
34 };
35
36 Ok(url)
37}
38
39struct UrlSerializer<'a> {
40 url: String,
42 parts: Vec<Part<'a>>,
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47enum Part<'a> {
48 Raw(&'a str),
50 Param(Param<'a>),
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55enum Param<'a> {
56 Key(&'a str),
58 Value(String),
60}
61
62fn to_string<T: Serialize>(base_url: &str, endpoint: &str, value: &T) -> Result<String, UrlError> {
63 let mut serializer = UrlSerializer {
64 url: base_url.to_owned(),
65 parts: parse_endpoint(endpoint)?,
66 };
67 value.serialize(&mut serializer)?;
68 serializer.end()
69}
70
71fn parse_endpoint(s: &str) -> Result<Vec<Part>, UrlError> {
83 let mut parts = Vec::new();
84 let mut start = 0;
85 let mut in_param = false;
86 for (i, c) in s.char_indices() {
87 if c == '{' {
89 if in_param {
91 return Err(UrlError::InvalidEndpoint);
92 }
93
94 in_param = true;
96
97 if start != i {
99 parts.push(Part::Raw(&s[start..i]));
100 }
101
102 start = i + 1;
104 } else if c == '}' {
105 if !in_param {
107 return Err(UrlError::InvalidEndpoint);
108 }
109
110 in_param = false;
112
113 if start != i {
115 parts.push(Part::Param(Param::Key(&s[start..i])));
116 }
117
118 start = i + 1;
120 }
121 }
122
123 if in_param {
125 return Err(UrlError::InvalidEndpoint);
126 }
127
128 if start != s.len() {
130 parts.push(Part::Raw(&s[start..]));
131 }
132
133 Ok(parts)
134}
135
136impl<'a> UrlSerializer<'a> {
137 pub fn end(self) -> Result<String, UrlError> {
138 let mut url = self.url;
139 for part in self.parts {
140 match part {
141 Part::Raw(s) => url.push_str(s),
142 Part::Param(p) => match p {
143 Param::Key(k) => return Err(UrlError::UnfilledField(k.to_owned())),
144 Param::Value(v) => url.push_str(&v),
145 },
146 }
147 }
148 Ok(url)
149 }
150}
151
152impl<'a, 'b> ser::Serializer for &'a mut UrlSerializer<'b> {
153 type Ok = ();
154
155 type Error = UrlError;
156 type SerializeSeq = ErrorSerializer;
157 type SerializeTuple = ErrorSerializer;
158 type SerializeTupleStruct = ErrorSerializer;
159 type SerializeTupleVariant = ErrorSerializer;
160 type SerializeMap = ErrorSerializer;
161 type SerializeStruct = Self;
162 type SerializeStructVariant = ErrorSerializer;
163
164 fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
165 Err(UrlError::TopLevel)
166 }
167
168 fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
169 Err(UrlError::TopLevel)
170 }
171
172 fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
173 Err(UrlError::TopLevel)
174 }
175
176 fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
177 Err(UrlError::TopLevel)
178 }
179
180 fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
181 Err(UrlError::TopLevel)
182 }
183
184 fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
185 Err(UrlError::TopLevel)
186 }
187
188 fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
189 Err(UrlError::TopLevel)
190 }
191
192 fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
193 Err(UrlError::TopLevel)
194 }
195
196 fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
197 Err(UrlError::TopLevel)
198 }
199
200 fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
201 Err(UrlError::TopLevel)
202 }
203
204 fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
205 Err(UrlError::TopLevel)
206 }
207
208 fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
209 Err(UrlError::TopLevel)
210 }
211
212 fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
213 Err(UrlError::TopLevel)
214 }
215
216 fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
217 Err(UrlError::TopLevel)
218 }
219
220 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
221 Ok(())
222 }
223
224 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
225 value.serialize(self)
226 }
227
228 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
229 Ok(())
230 }
231
232 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
233 Ok(())
234 }
235
236 fn serialize_unit_variant(
237 self,
238 _name: &'static str,
239 _variant_index: u32,
240 _variant: &'static str,
241 ) -> Result<Self::Ok, Self::Error> {
242 Err(UrlError::TopLevel)
243 }
244
245 fn serialize_newtype_struct<T: ?Sized + Serialize>(
246 self,
247 _name: &'static str,
248 value: &T,
249 ) -> Result<Self::Ok, Self::Error> {
250 value.serialize(self)
251 }
252
253 fn serialize_newtype_variant<T: ?Sized + Serialize>(
254 self,
255 _name: &'static str,
256 _variant_index: u32,
257 _variant: &'static str,
258 _value: &T,
259 ) -> Result<Self::Ok, Self::Error> {
260 Err(UrlError::TopLevel)
261 }
262
263 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
264 Err(UrlError::ValueNotSupported)
265 }
266
267 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
268 Err(UrlError::ValueNotSupported)
269 }
270
271 fn serialize_tuple_struct(
272 self,
273 _name: &'static str,
274 _len: usize,
275 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
276 Err(UrlError::ValueNotSupported)
277 }
278
279 fn serialize_tuple_variant(
280 self,
281 _name: &'static str,
282 _variant_index: u32,
283 _variant: &'static str,
284 _len: usize,
285 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
286 Err(UrlError::ValueNotSupported)
287 }
288
289 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
290 Err(UrlError::ValueNotSupported)
291 }
292
293 fn serialize_struct(
294 self,
295 _name: &'static str,
296 _len: usize,
297 ) -> Result<Self::SerializeStruct, Self::Error> {
298 Ok(self)
299 }
300
301 fn serialize_struct_variant(
302 self,
303 _name: &'static str,
304 _variant_index: u32,
305 _variant: &'static str,
306 _len: usize,
307 ) -> Result<Self::SerializeStructVariant, Self::Error> {
308 Err(UrlError::ValueNotSupported)
309 }
310}
311
312impl<'a, 'b> ser::SerializeStruct for &'a mut UrlSerializer<'b> {
313 type Ok = ();
314 type Error = UrlError;
315
316 fn serialize_field<T: ?Sized + Serialize>(
317 &mut self,
318 key: &'static str,
319 value: &T,
320 ) -> Result<(), Self::Error> {
321 let mut part = None;
323 for p in &mut self.parts {
324 match p {
325 Part::Param(p) => match p {
326 Param::Key(k) if *k == key => {
327 part = Some(p);
328 break;
329 }
330 _ => {}
331 },
332 Part::Raw(_) => {}
333 }
334 }
335
336 let part = part.ok_or(UrlError::KeyNotFound(key))?;
338
339 let mut serializer = UrlValueSerializer::default();
341 value.serialize(&mut serializer)?;
342 let value = serializer.value;
343
344 *part = Param::Value(value);
345
346 Ok(())
347 }
348
349 fn end(self) -> Result<Self::Ok, Self::Error> {
350 Ok(())
351 }
352}
353
354#[derive(Debug, Clone, Default)]
355struct UrlValueSerializer {
356 value: String,
357}
358
359const PATH_SET: &AsciiSet = &CONTROLS
360 .add(b'~')
361 .add(b' ')
362 .add(b'"')
363 .add(b'#')
364 .add(b'<')
365 .add(b'>')
366 .add(b'?')
367 .add(b'`')
368 .add(b'{')
369 .add(b'}');
370
371impl<'a> ser::Serializer for &'a mut UrlValueSerializer {
372 type Ok = ();
373 type Error = UrlError;
374
375 type SerializeSeq = ErrorSerializer;
376 type SerializeTuple = ErrorSerializer;
377 type SerializeTupleStruct = ErrorSerializer;
378 type SerializeTupleVariant = ErrorSerializer;
379 type SerializeMap = ErrorSerializer;
380 type SerializeStruct = ErrorSerializer;
381 type SerializeStructVariant = ErrorSerializer;
382
383 fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
384 self.value = utf8_percent_encode(if v { "true" } else { "false" });
385 Ok(())
386 }
387
388 fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
389 let mut buffer = itoa::Buffer::new();
390 self.value = utf8_percent_encode(buffer.format(v));
391 Ok(())
392 }
393
394 fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
395 let mut buffer = itoa::Buffer::new();
396 self.value = utf8_percent_encode(buffer.format(v));
397 Ok(())
398 }
399
400 fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
401 let mut buffer = itoa::Buffer::new();
402 self.value = utf8_percent_encode(buffer.format(v));
403 Ok(())
404 }
405
406 fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
407 let mut buffer = itoa::Buffer::new();
408 self.value = utf8_percent_encode(buffer.format(v));
409 Ok(())
410 }
411
412 fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
413 let mut buffer = itoa::Buffer::new();
414 self.value = utf8_percent_encode(buffer.format(v));
415 Ok(())
416 }
417
418 fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
419 let mut buffer = itoa::Buffer::new();
420 self.value = utf8_percent_encode(buffer.format(v));
421 Ok(())
422 }
423
424 fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
425 let mut buffer = itoa::Buffer::new();
426 self.value = utf8_percent_encode(buffer.format(v));
427 Ok(())
428 }
429
430 fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
431 let mut buffer = itoa::Buffer::new();
432 self.value = utf8_percent_encode(buffer.format(v));
433 Ok(())
434 }
435
436 fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
437 let mut buf = ryu::Buffer::new();
438 self.value = utf8_percent_encode(buf.format(v));
439 Ok(())
440 }
441
442 fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
443 let mut buf = ryu::Buffer::new();
444 self.value = utf8_percent_encode(buf.format(v));
445 Ok(())
446 }
447
448 fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
449 let mut buf = [0; 4];
450 self.value = utf8_percent_encode(v.encode_utf8(&mut buf));
451 Ok(())
452 }
453
454 fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
455 self.value = utf8_percent_encode(v);
456 Ok(())
457 }
458
459 fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
460 self.value = percent_encoding::percent_encode(v, PATH_SET).to_string();
461 Ok(())
462 }
463
464 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
465 self.serialize_unit()
466 }
467
468 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
469 value.serialize(self)
470 }
471
472 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
473 self.value = utf8_percent_encode("");
474 Ok(())
475 }
476
477 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
478 self.serialize_unit()
479 }
480
481 fn serialize_unit_variant(
482 self,
483 _name: &'static str,
484 _variant_index: u32,
485 variant: &'static str,
486 ) -> Result<Self::Ok, Self::Error> {
487 self.value = utf8_percent_encode(variant);
488 Ok(())
489 }
490
491 fn serialize_newtype_struct<T: ?Sized + Serialize>(
492 self,
493 _name: &'static str,
494 value: &T,
495 ) -> Result<Self::Ok, Self::Error> {
496 value.serialize(self)
497 }
498
499 fn serialize_newtype_variant<T: ?Sized + Serialize>(
500 self,
501 _name: &'static str,
502 _variant_index: u32,
503 _variant: &'static str,
504 value: &T,
505 ) -> Result<Self::Ok, Self::Error> {
506 value.serialize(self)
507 }
508
509 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
510 Err(UrlError::ValueNotSupported)
511 }
512
513 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
514 Err(UrlError::ValueNotSupported)
515 }
516
517 fn serialize_tuple_struct(
518 self,
519 _name: &'static str,
520 _len: usize,
521 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
522 Err(UrlError::ValueNotSupported)
523 }
524
525 fn serialize_tuple_variant(
526 self,
527 _name: &'static str,
528 _variant_index: u32,
529 _variant: &'static str,
530 _len: usize,
531 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
532 Err(UrlError::ValueNotSupported)
533 }
534
535 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
536 Err(UrlError::ValueNotSupported)
537 }
538
539 fn serialize_struct(
540 self,
541 _name: &'static str,
542 _len: usize,
543 ) -> Result<Self::SerializeStruct, Self::Error> {
544 Err(UrlError::ValueNotSupported)
545 }
546
547 fn serialize_struct_variant(
548 self,
549 _name: &'static str,
550 _variant_index: u32,
551 _variant: &'static str,
552 _len: usize,
553 ) -> Result<Self::SerializeStructVariant, Self::Error> {
554 Err(UrlError::ValueNotSupported)
555 }
556}
557
558#[derive(Debug)]
559struct ErrorSerializer;
560
561impl ser::SerializeSeq for ErrorSerializer {
562 type Ok = ();
563 type Error = UrlError;
564
565 fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), Self::Error> {
566 Err(UrlError::ValueNotSupported)
567 }
568
569 fn end(self) -> Result<Self::Ok, Self::Error> {
570 Err(UrlError::ValueNotSupported)
571 }
572}
573
574impl ser::SerializeTuple for ErrorSerializer {
575 type Ok = ();
576 type Error = UrlError;
577
578 fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), Self::Error> {
579 Err(UrlError::ValueNotSupported)
580 }
581
582 fn end(self) -> Result<Self::Ok, Self::Error> {
583 Err(UrlError::ValueNotSupported)
584 }
585}
586
587impl ser::SerializeTupleStruct for ErrorSerializer {
588 type Ok = ();
589 type Error = UrlError;
590
591 fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), Self::Error> {
592 Err(UrlError::ValueNotSupported)
593 }
594
595 fn end(self) -> Result<Self::Ok, Self::Error> {
596 Err(UrlError::ValueNotSupported)
597 }
598}
599
600impl ser::SerializeTupleVariant for ErrorSerializer {
601 type Ok = ();
602 type Error = UrlError;
603
604 fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), Self::Error> {
605 Err(UrlError::ValueNotSupported)
606 }
607
608 fn end(self) -> Result<Self::Ok, Self::Error> {
609 Err(UrlError::ValueNotSupported)
610 }
611}
612
613impl ser::SerializeMap for ErrorSerializer {
614 type Ok = ();
615 type Error = UrlError;
616
617 fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), Self::Error> {
618 Err(UrlError::ValueNotSupported)
619 }
620
621 fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), Self::Error> {
622 Err(UrlError::ValueNotSupported)
623 }
624
625 fn end(self) -> Result<Self::Ok, Self::Error> {
626 Err(UrlError::ValueNotSupported)
627 }
628}
629
630impl ser::SerializeStruct for ErrorSerializer {
631 type Ok = ();
632 type Error = UrlError;
633
634 fn serialize_field<T: ?Sized + Serialize>(
635 &mut self,
636 _key: &'static str,
637 _value: &T,
638 ) -> Result<(), Self::Error> {
639 Err(UrlError::ValueNotSupported)
640 }
641
642 fn end(self) -> Result<Self::Ok, Self::Error> {
643 Err(UrlError::ValueNotSupported)
644 }
645}
646
647impl ser::SerializeStructVariant for ErrorSerializer {
648 type Ok = ();
649 type Error = UrlError;
650
651 fn serialize_field<T: ?Sized + Serialize>(
652 &mut self,
653 _key: &'static str,
654 _value: &T,
655 ) -> Result<(), Self::Error> {
656 Err(UrlError::ValueNotSupported)
657 }
658
659 fn end(self) -> Result<Self::Ok, Self::Error> {
660 Err(UrlError::ValueNotSupported)
661 }
662}
663
664fn utf8_percent_encode(input: &str) -> String {
665 percent_encoding::utf8_percent_encode(input, PATH_SET).to_string()
666}
667
668#[cfg(test)]
669mod tests {
670 use serde::Serializer;
671
672 use super::*;
673
674 #[test]
675 fn test_parse_endpoint() {
676 let endpoint = "/shows/{id}/seasons/{season}/episodes/{episode}";
677 let parts = parse_endpoint(endpoint).unwrap();
678 assert_eq!(
679 parts,
680 vec![
681 Part::Raw("/shows/"),
682 Part::Param(Param::Key("id")),
683 Part::Raw("/seasons/"),
684 Part::Param(Param::Key("season")),
685 Part::Raw("/episodes/"),
686 Part::Param(Param::Key("episode")),
687 ]
688 );
689
690 let endpoint = "/shows/{id}/seasons/{season}/episodes/{episode}/";
691 let parts = parse_endpoint(endpoint).unwrap();
692 assert_eq!(
693 parts,
694 vec![
695 Part::Raw("/shows/"),
696 Part::Param(Param::Key("id")),
697 Part::Raw("/seasons/"),
698 Part::Param(Param::Key("season")),
699 Part::Raw("/episodes/"),
700 Part::Param(Param::Key("episode")),
701 Part::Raw("/"),
702 ]
703 );
704
705 assert_eq!(
706 parse_endpoint("/shows/{{id}}").unwrap_err(),
707 UrlError::InvalidEndpoint
708 );
709 assert_eq!(
710 parse_endpoint("/shows/{id}}").unwrap_err(),
711 UrlError::InvalidEndpoint
712 );
713 assert_eq!(
714 parse_endpoint("/shows/{id").unwrap_err(),
715 UrlError::InvalidEndpoint
716 );
717 }
718
719 #[test]
720 fn construct_url_normal() {
721 #[derive(Serialize)]
722 struct Params {
723 id: i32,
724 }
725 #[derive(Serialize)]
726 struct Query {
727 page: i32,
728 limit: Option<i32>,
729 }
730
731 let base_url = "https://example.com";
732 let endpoint = "/shows/{id}";
733 let params = Params { id: 1 };
734 let query = Query {
735 page: 1,
736 limit: None,
737 };
738
739 let url = construct_url(base_url, endpoint, ¶ms, &query).unwrap();
740 assert_eq!(url, "https://example.com/shows/1?page=1");
741 }
742
743 #[test]
744 fn construct_url_no_query() {
745 #[derive(Serialize)]
746 struct Params {
747 id: i32,
748 }
749 #[derive(Serialize)]
750 struct Query;
751
752 let base_url = "https://example.com";
753 let endpoint = "/shows/{id}";
754 let params = Params { id: 1 };
755 let query = Query;
756
757 let url = construct_url(base_url, endpoint, ¶ms, &query).unwrap();
758 assert_eq!(url, "https://example.com/shows/1");
759 }
760
761 #[test]
762 fn construct_url_unfilled() {
763 #[derive(Serialize)]
764 struct Params {
765 id: i32,
766 }
767 #[derive(Serialize)]
768 struct Query;
769
770 let base_url = "https://example.com";
771 let endpoint = "/shows/{id}/{unfilled}";
772 let params = Params { id: 1 };
773 let query = Query;
774
775 let res = construct_url(base_url, endpoint, ¶ms, &query).unwrap_err();
776 assert_eq!(
777 res.to_string(),
778 "Url params error: Unfilled field: unfilled"
779 );
780 }
781
782 #[test]
783 fn construct_url_invalid_endpoint() {
784 #[derive(Serialize)]
785 struct Params {
786 id: i32,
787 }
788 #[derive(Serialize)]
789 struct Query;
790
791 let base_url = "https://example.com";
792 let endpoint = "/shows/{{id}";
793 let params = Params { id: 1 };
794 let query = Query;
795
796 let res = construct_url(base_url, endpoint, ¶ms, &query).unwrap_err();
797 assert_eq!(res.to_string(), "Url params error: Invalid endpoint");
798 }
799
800 #[test]
801 fn construct_url_empty() {
802 #[derive(Serialize)]
803 struct Params;
804 #[derive(Serialize)]
805 struct Query;
806
807 let base_url = "https://example.com";
808 let endpoint = "/shows";
809 let params = Params;
810 let query = Query;
811
812 let url = construct_url(base_url, endpoint, ¶ms, &query).unwrap();
813 assert_eq!(url, "https://example.com/shows");
814 }
815
816 #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
817 #[test]
818 fn url_value_serializer() {
819 let mut serializer = UrlValueSerializer::default();
820 serializer.serialize_bool(true).unwrap();
821 assert_eq!(serializer.value, "true");
822
823 let mut serializer = UrlValueSerializer::default();
824 serializer.serialize_bool(false).unwrap();
825 assert_eq!(serializer.value, "false");
826
827 let mut serializer = UrlValueSerializer::default();
828 serializer.serialize_i8(1).unwrap();
829 assert_eq!(serializer.value, "1");
830
831 let mut serializer = UrlValueSerializer::default();
832 serializer.serialize_i16(-1).unwrap();
833 assert_eq!(serializer.value, "-1");
834
835 let mut serializer = UrlValueSerializer::default();
836 serializer.serialize_i32(1024).unwrap();
837 assert_eq!(serializer.value, "1024");
838
839 let mut serializer = UrlValueSerializer::default();
840 serializer.serialize_i64(1024).unwrap();
841 assert_eq!(serializer.value, "1024");
842
843 let mut serializer = UrlValueSerializer::default();
844 serializer.serialize_u8(1).unwrap();
845 assert_eq!(serializer.value, "1");
846
847 let mut serializer = UrlValueSerializer::default();
848 serializer.serialize_u16(256).unwrap();
849 assert_eq!(serializer.value, "256");
850
851 let mut serializer = UrlValueSerializer::default();
852 serializer.serialize_u32(1024).unwrap();
853 assert_eq!(serializer.value, "1024");
854
855 let mut serializer = UrlValueSerializer::default();
856 serializer.serialize_u64(1024).unwrap();
857 assert_eq!(serializer.value, "1024");
858
859 let mut serializer = UrlValueSerializer::default();
860 serializer.serialize_f32(2.5).unwrap();
861 assert_eq!(serializer.value, "2.5");
862
863 let mut serializer = UrlValueSerializer::default();
864 serializer.serialize_f64(-2.5).unwrap();
865 assert_eq!(serializer.value, "-2.5");
866
867 let mut serializer = UrlValueSerializer::default();
868 serializer.serialize_char('a').unwrap();
869 assert_eq!(serializer.value, "a");
870
871 let mut serializer = UrlValueSerializer::default();
872 serializer.serialize_char('🚀').unwrap();
873 assert_eq!(serializer.value, "%F0%9F%9A%80");
874
875 let mut serializer = UrlValueSerializer::default();
876 serializer.serialize_str("hello?").unwrap();
877 assert_eq!(serializer.value, "hello%3F");
878
879 let mut serializer = UrlValueSerializer::default();
880 serializer.serialize_bytes(b"hello?\xc3\x28\x00").unwrap();
881 assert_eq!(serializer.value, "hello%3F%C3(%00");
882
883 let mut serializer = UrlValueSerializer::default();
884 serializer.serialize_none().unwrap();
885 assert_eq!(serializer.value, "");
886
887 let mut serializer = UrlValueSerializer::default();
888 serializer.serialize_some(&true).unwrap();
889 assert_eq!(serializer.value, "true");
890
891 let mut serializer = UrlValueSerializer::default();
892 serializer.serialize_unit().unwrap();
893 assert_eq!(serializer.value, "");
894
895 let mut serializer = UrlValueSerializer::default();
896 serializer.serialize_unit_struct("name").unwrap();
897 assert_eq!(serializer.value, "");
898
899 let mut serializer = UrlValueSerializer::default();
900 serializer
901 .serialize_unit_variant("name", 0, "variant")
902 .unwrap();
903 assert_eq!(serializer.value, "variant");
904
905 let mut serializer = UrlValueSerializer::default();
906 serializer.serialize_newtype_struct("name", &true).unwrap();
907 assert_eq!(serializer.value, "true");
908
909 let mut serializer = UrlValueSerializer::default();
910 serializer
911 .serialize_newtype_variant("name", 0, "variant", &true)
912 .unwrap();
913 assert_eq!(serializer.value, "true");
914
915 let mut serializer = UrlValueSerializer::default();
916 assert_eq!(
917 serializer.serialize_seq(None).unwrap_err(),
918 UrlError::ValueNotSupported
919 );
920
921 let mut serializer = UrlValueSerializer::default();
922 assert_eq!(
923 serializer.serialize_tuple(0).unwrap_err(),
924 UrlError::ValueNotSupported
925 );
926
927 let mut serializer = UrlValueSerializer::default();
928 assert_eq!(
929 serializer.serialize_tuple_struct("name", 0).unwrap_err(),
930 UrlError::ValueNotSupported
931 );
932
933 let mut serializer = UrlValueSerializer::default();
934 assert_eq!(
935 serializer
936 .serialize_tuple_variant("name", 0, "variant", 0)
937 .unwrap_err(),
938 UrlError::ValueNotSupported
939 );
940
941 let mut serializer = UrlValueSerializer::default();
942 assert_eq!(
943 serializer.serialize_map(None).unwrap_err(),
944 UrlError::ValueNotSupported
945 );
946
947 let mut serializer = UrlValueSerializer::default();
948 assert_eq!(
949 serializer.serialize_struct("name", 0).unwrap_err(),
950 UrlError::ValueNotSupported
951 );
952
953 let mut serializer = UrlValueSerializer::default();
954 assert_eq!(
955 serializer
956 .serialize_struct_variant("name", 0, "variant", 0)
957 .unwrap_err(),
958 UrlError::ValueNotSupported
959 );
960 }
961
962 #[allow(clippy::too_many_lines)]
963 #[test]
964 fn url_serializer() {
965 let mut serializer = UrlSerializer {
966 url: String::new(),
967 parts: vec![],
968 };
969
970 assert_eq!(
971 true.serialize(&mut serializer).unwrap_err(),
972 UrlError::TopLevel
973 );
974 assert_eq!(
975 1i8.serialize(&mut serializer).unwrap_err(),
976 UrlError::TopLevel
977 );
978 assert_eq!(
979 1i16.serialize(&mut serializer).unwrap_err(),
980 UrlError::TopLevel
981 );
982 assert_eq!(
983 1i32.serialize(&mut serializer).unwrap_err(),
984 UrlError::TopLevel
985 );
986 assert_eq!(
987 1i64.serialize(&mut serializer).unwrap_err(),
988 UrlError::TopLevel
989 );
990 assert_eq!(
991 1u8.serialize(&mut serializer).unwrap_err(),
992 UrlError::TopLevel
993 );
994 assert_eq!(
995 1u16.serialize(&mut serializer).unwrap_err(),
996 UrlError::TopLevel
997 );
998 assert_eq!(
999 1u32.serialize(&mut serializer).unwrap_err(),
1000 UrlError::TopLevel
1001 );
1002 assert_eq!(
1003 1u64.serialize(&mut serializer).unwrap_err(),
1004 UrlError::TopLevel
1005 );
1006 assert_eq!(
1007 2.5f32.serialize(&mut serializer).unwrap_err(),
1008 UrlError::TopLevel
1009 );
1010 assert_eq!(
1011 (-2.5f64).serialize(&mut serializer).unwrap_err(),
1012 UrlError::TopLevel
1013 );
1014 assert_eq!(
1015 'a'.serialize(&mut serializer).unwrap_err(),
1016 UrlError::TopLevel
1017 );
1018 assert_eq!(
1019 "hello?".serialize(&mut serializer).unwrap_err(),
1020 UrlError::TopLevel
1021 );
1022 assert_eq!(
1023 serializer
1024 .serialize_bytes(b"hello?\xc3\x28\x00")
1025 .unwrap_err(),
1026 UrlError::TopLevel
1027 );
1028 assert!(None::<bool>.serialize(&mut serializer).is_ok());
1029 assert_eq!(
1030 Some(true).serialize(&mut serializer).unwrap_err(),
1031 UrlError::TopLevel
1032 );
1033 assert!(().serialize(&mut serializer).is_ok());
1034 assert_eq!(
1035 "name".serialize(&mut serializer).unwrap_err(),
1036 UrlError::TopLevel
1037 );
1038 assert_eq!(
1039 (0, "variant").serialize(&mut serializer).unwrap_err(),
1040 UrlError::ValueNotSupported
1041 );
1042 assert_eq!(
1043 Ok::<_, bool>(true).serialize(&mut serializer).unwrap_err(),
1044 UrlError::TopLevel
1045 );
1046
1047 #[allow(clippy::items_after_statements)]
1048 #[derive(Serialize)]
1049 struct Params {
1050 id: i32,
1051 }
1052 let params = Params { id: 1 };
1053
1054 let mut serializer = UrlSerializer {
1055 url: String::new(),
1056 parts: vec![
1057 Part::Param(Param::Value("raw".to_owned())),
1058 Part::Param(Param::Key("id")),
1059 ],
1060 };
1061
1062 params.serialize(&mut serializer).unwrap();
1063 assert_eq!(
1064 serializer.parts,
1065 vec![
1066 Part::Param(Param::Value("raw".to_owned())),
1067 Part::Param(Param::Value("1".to_owned())),
1068 ]
1069 );
1070
1071 let params = Params { id: 1 };
1072
1073 let mut serializer = UrlSerializer {
1074 url: String::new(),
1075 parts: vec![
1076 Part::Param(Param::Value("raw".to_owned())),
1077 Part::Param(Param::Key("i")),
1078 ],
1079 };
1080
1081 assert_eq!(
1082 params.serialize(&mut serializer).unwrap_err(),
1083 UrlError::KeyNotFound("id")
1084 );
1085 }
1086}