serde_querystring/
decode.rs1use std::borrow::{Borrow, Cow};
2
3#[inline]
5pub fn parse_char(h: u8, l: u8) -> Option<u8> {
6 Some(char::from(h).to_digit(16)? as u8 * 0x10 + char::from(l).to_digit(16)? as u8)
7}
8
9pub fn parse_bytes<'de, 's>(
11 slice: &'de [u8],
12 scratch: &'s mut Vec<u8>,
13) -> Reference<'de, 's, [u8]> {
14 scratch.clear();
15
16 let mut index = 0;
18
19 let mut cursor = 0;
21
22 while let Some(v) = slice.get(cursor) {
23 match v {
24 b'+' => {
25 scratch.extend_from_slice(&slice[index..cursor]);
26 scratch.push(b' ');
27
28 cursor += 1;
29 index = cursor;
30 }
31 b'%' => {
32 if slice.len() > cursor + 2 {
34 match parse_char(slice[cursor + 1], slice[cursor + 2]) {
35 Some(b) => {
36 scratch.extend_from_slice(&slice[index..cursor]);
37 scratch.push(b);
38
39 cursor += 3;
40 index = cursor;
41 }
42 None => {
43 cursor += 1;
45 }
46 }
47 } else {
48 cursor += 1;
49 }
50 }
51 _ => {
52 cursor += 1;
53 }
54 }
55 }
56
57 if scratch.is_empty() {
58 Reference::Borrowed(&slice[index..cursor])
59 } else {
60 scratch.extend_from_slice(&slice[index..cursor]);
61 Reference::Copied(scratch)
62 }
63}
64
65pub enum Reference<'b, 'c, T>
70where
71 T: ?Sized + 'static + ToOwned,
72{
73 Borrowed(&'b T),
74 Copied(&'c T),
75 Owned(<T as ToOwned>::Owned),
76}
77
78impl<'b, 'c, T> Reference<'b, 'c, T>
79where
80 T: ?Sized + ToOwned + 'static,
81{
82 pub fn into_cow(self) -> Cow<'b, T> {
83 match self {
84 Reference::Borrowed(b) => Cow::Borrowed(b),
85 Reference::Copied(c) => Cow::Owned(c.to_owned()),
86 Reference::Owned(o) => Cow::Owned(o),
87 }
88 }
89
90 pub fn try_map<F, B, E>(self, f: F) -> Result<Reference<'b, 'c, B>, E>
91 where
92 F: FnOnce(&T) -> Result<&B, E>,
93 B: ?Sized + ToOwned + 'static,
94 {
95 match self {
96 Reference::Borrowed(b) => f(b).map(Reference::Borrowed),
97 Reference::Copied(c) => f(c).map(Reference::Copied),
98 Reference::Owned(o) => f(o.borrow()).map(|o| Reference::Owned(o.to_owned())),
99 }
100 }
101}
102
103impl<'b, 'c, T> std::ops::Deref for Reference<'b, 'c, T>
104where
105 T: ?Sized + 'static + ToOwned,
106{
107 type Target = T;
108
109 fn deref(&self) -> &Self::Target {
110 match *self {
111 Reference::Borrowed(b) => b,
112 Reference::Copied(c) => c,
113 Reference::Owned(ref o) => o.borrow(),
114 }
115 }
116}