1#[derive(Clone, Debug)]
34pub struct QueryIter<'a> {
35 rest: &'a [u8],
36}
37
38impl<'a> Iterator for QueryIter<'a> {
39 type Item = (&'a [u8], &'a [u8]);
40
41 fn next(&mut self) -> Option<Self::Item> {
42 loop {
44 if self.rest.is_empty() {
45 return None;
46 }
47 if self.rest[0] == b'&' {
48 self.rest = &self.rest[1..];
49 continue;
50 }
51 break;
52 }
53
54 let (segment, tail) = self.rest.iter().position(|&b| b == b'&').map_or_else(
55 || (self.rest, &b""[..]),
56 |amp| (&self.rest[..amp], &self.rest[amp + 1..]),
57 );
58 self.rest = tail;
59
60 let (name, value) = segment.iter().position(|&b| b == b'=').map_or_else(
61 || (segment, &b""[..]),
62 |eq| (&segment[..eq], &segment[eq + 1..]),
63 );
64 Some((name, value))
65 }
66}
67
68#[inline]
73#[must_use]
74pub const fn parse(query: &[u8]) -> QueryIter<'_> {
75 QueryIter { rest: query }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 fn collect(input: &[u8]) -> Vec<(&[u8], &[u8])> {
83 parse(input).collect()
84 }
85
86 #[test]
87 fn empty_input() {
88 assert!(collect(b"").is_empty());
89 }
90
91 #[test]
92 fn single_pair() {
93 assert_eq!(collect(b"a=1"), &[(&b"a"[..], &b"1"[..])]);
94 }
95
96 #[test]
97 fn multiple_pairs() {
98 assert_eq!(
99 collect(b"a=1&b=2&c=3"),
100 &[
101 (&b"a"[..], &b"1"[..]),
102 (&b"b"[..], &b"2"[..]),
103 (&b"c"[..], &b"3"[..]),
104 ]
105 );
106 }
107
108 #[test]
109 fn name_without_value() {
110 assert_eq!(collect(b"flag"), &[(&b"flag"[..], &b""[..])]);
111 assert_eq!(
112 collect(b"a=1&flag&b=2"),
113 &[
114 (&b"a"[..], &b"1"[..]),
115 (&b"flag"[..], &b""[..]),
116 (&b"b"[..], &b"2"[..]),
117 ]
118 );
119 }
120
121 #[test]
122 fn empty_value() {
123 assert_eq!(collect(b"a="), &[(&b"a"[..], &b""[..])]);
124 }
125
126 #[test]
127 fn empty_name() {
128 assert_eq!(collect(b"=v"), &[(&b""[..], &b"v"[..])]);
129 }
130
131 #[test]
132 fn skip_empty_segments() {
133 assert_eq!(collect(b"&&a=1"), &[(&b"a"[..], &b"1"[..])]);
134 assert_eq!(
135 collect(b"a=1&&b=2"),
136 &[(&b"a"[..], &b"1"[..]), (&b"b"[..], &b"2"[..])]
137 );
138 assert!(collect(b"&&&").is_empty());
139 }
140
141 #[test]
142 fn value_contains_equals() {
143 assert_eq!(collect(b"a=1=2"), &[(&b"a"[..], &b"1=2"[..])]);
145 }
146
147 #[test]
148 fn raw_undecoded_output() {
149 assert_eq!(
151 collect(b"q=hello+world&n=foo%20bar"),
152 &[
153 (&b"q"[..], &b"hello+world"[..]),
154 (&b"n"[..], &b"foo%20bar"[..]),
155 ]
156 );
157 }
158
159 #[test]
160 fn iterator_is_lazy_and_clone() {
161 let iter = parse(b"a=1&b=2");
162 let mut a = iter.clone();
163 let mut b = iter;
164 assert_eq!(a.next(), Some((&b"a"[..], &b"1"[..])));
165 assert_eq!(b.next(), Some((&b"a"[..], &b"1"[..])));
166 }
167
168 #[test]
169 fn integrates_with_pct_form_decode() {
170 use crate::pct::{Mode, decode};
171
172 let pairs: Vec<_> = parse(b"q=hello+world").collect();
173 let (name, value) = pairs[0];
174 let mut nbuf = [0u8; 16];
175 let mut vbuf = [0u8; 16];
176 assert_eq!(decode(name, Mode::Form, &mut nbuf).unwrap(), b"q");
177 assert_eq!(
178 decode(value, Mode::Form, &mut vbuf).unwrap(),
179 b"hello world"
180 );
181 }
182}