1use crate::argv::Argv;
15use crate::argv_borrowed::ArgvBorrowed;
16
17pub trait ArgvView: core::ops::Index<usize, Output = [u8]> {
23 fn len(&self) -> usize;
25 fn get(&self, i: usize) -> Option<&[u8]>;
27
28 fn is_empty(&self) -> bool {
30 self.len() == 0
31 }
32
33 fn first(&self) -> Option<&[u8]> {
35 self.get(0)
36 }
37
38 fn iter(&self) -> ArgvIter<'_, Self>
40 where
41 Self: Sized,
42 {
43 ArgvIter { view: self, i: 0 }
44 }
45
46 fn copy_into(&self, out: &mut Argv) {
51 out.clear();
52 let n = self.len();
53 let total: usize = (0..n).map(|i| self.get(i).map_or(0, <[u8]>::len)).sum();
54 out.reserve_for(n, total);
55 for i in 0..n {
56 if let Some(arg) = self.get(i) {
57 out.push(arg);
58 }
59 }
60 }
61
62 fn to_argv(&self) -> Argv {
67 let mut out = Argv::default();
68 self.copy_into(&mut out);
69 out
70 }
71}
72
73pub struct ArgvIter<'a, V: ?Sized + ArgvView> {
78 view: &'a V,
79 i: usize,
80}
81
82impl<'a, V: ?Sized + ArgvView> Iterator for ArgvIter<'a, V> {
83 type Item = &'a [u8];
84 fn next(&mut self) -> Option<&'a [u8]> {
85 let r = self.view.get(self.i);
86 if r.is_some() {
87 self.i += 1;
88 }
89 r
90 }
91 fn size_hint(&self) -> (usize, Option<usize>) {
92 let rem = self.view.len().saturating_sub(self.i);
93 (rem, Some(rem))
94 }
95}
96
97impl<V: ?Sized + ArgvView> ExactSizeIterator for ArgvIter<'_, V> {}
98
99impl ArgvView for Argv {
100 fn len(&self) -> usize {
101 Argv::len(self)
102 }
103 fn get(&self, i: usize) -> Option<&[u8]> {
104 Argv::get(self, i)
105 }
106}
107
108impl ArgvView for ArgvBorrowed<'_> {
109 fn len(&self) -> usize {
110 ArgvBorrowed::len(self)
111 }
112 fn get(&self, i: usize) -> Option<&[u8]> {
113 ArgvBorrowed::get(self, i)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 fn first_arg<A: ArgvView>(a: &A) -> Option<&[u8]> {
122 a.first()
123 }
124
125 fn arg_at<A: ArgvView>(a: &A, i: usize) -> &[u8] {
126 &a[i]
127 }
128
129 fn collect_iter<A: ArgvView>(a: &A) -> Vec<Vec<u8>> {
130 a.iter().map(|s| s.to_vec()).collect()
131 }
132
133 #[test]
134 fn argv_implements_argv_view() {
135 let mut a = Argv::default();
136 a.push(b"SET");
137 a.push(b"k");
138 a.push(b"v");
139 assert_eq!(ArgvView::len(&a), 3);
140 assert_eq!(first_arg(&a), Some(b"SET" as &[u8]));
141 assert_eq!(arg_at(&a, 1), b"k" as &[u8]);
142 assert_eq!(
143 collect_iter(&a),
144 vec![b"SET".to_vec(), b"k".to_vec(), b"v".to_vec()]
145 );
146 }
147
148 #[test]
149 fn argv_borrowed_implements_argv_view() {
150 let buf: &[u8] = b"abcdef";
151 let mut a = ArgvBorrowed::new(buf);
152 a.push_range(0, 3); a.push_range(3, 6); assert_eq!(ArgvView::len(&a), 2);
155 assert_eq!(first_arg(&a), Some(b"abc" as &[u8]));
156 assert_eq!(arg_at(&a, 1), b"def" as &[u8]);
157 assert_eq!(collect_iter(&a), vec![b"abc".to_vec(), b"def".to_vec()]);
158 }
159
160 #[test]
161 fn iter_size_hint_is_exact() {
162 let mut a = Argv::default();
163 a.push(b"A");
164 a.push(b"B");
165 a.push(b"C");
166 let it = ArgvView::iter(&a);
167 assert_eq!(it.size_hint(), (3, Some(3)));
168 assert_eq!(it.len(), 3);
169 }
170
171 #[test]
172 fn empty_argv_iter_yields_nothing() {
173 let a = Argv::default();
174 assert!(ArgvView::is_empty(&a));
175 assert_eq!(first_arg(&a), None);
176 let mut it = ArgvView::iter(&a);
177 assert!(it.next().is_none());
178 }
179
180 #[test]
181 fn generic_over_owned_and_borrowed_with_same_api() {
182 fn route_name<A: ArgvView>(a: &A) -> &[u8] {
184 a.first().unwrap_or(b"")
185 }
186 let mut owned = Argv::default();
187 owned.push(b"PING");
188 let buf: &[u8] = b"PING";
189 let mut borrowed = ArgvBorrowed::new(buf);
190 borrowed.push_range(0, 4);
191 assert_eq!(route_name(&owned), b"PING");
192 assert_eq!(route_name(&borrowed), b"PING");
193 }
194}