1#[derive(Clone, Default, Debug, Eq)]
16pub struct Argv {
17 buf: Vec<u8>,
18 ends: Vec<u32>,
19}
20
21impl Argv {
22 pub fn with_capacity(argc: usize, bytes: usize) -> Self {
24 Argv {
25 buf: Vec::with_capacity(bytes),
26 ends: Vec::with_capacity(argc),
27 }
28 }
29
30 #[inline]
34 pub fn clear(&mut self) {
35 self.buf.clear();
36 self.ends.clear();
37 }
38
39 #[inline]
42 pub fn reserve_for(&mut self, argc: usize, bytes: usize) {
43 self.buf.reserve(bytes);
44 self.ends.reserve(argc);
45 }
46
47 pub(crate) fn buf_capacity(&self) -> usize {
50 self.buf.capacity()
51 }
52
53 pub fn push(&mut self, arg: &[u8]) {
55 self.buf.extend_from_slice(arg);
56 self.ends.push(self.buf.len() as u32);
57 }
58
59 pub fn len(&self) -> usize {
61 self.ends.len()
62 }
63
64 pub fn is_empty(&self) -> bool {
66 self.ends.is_empty()
67 }
68
69 pub fn get(&self, i: usize) -> Option<&[u8]> {
71 let end = *self.ends.get(i)? as usize;
72 let start = if i == 0 { 0 } else { self.ends[i - 1] as usize };
73 Some(&self.buf[start..end])
74 }
75
76 pub fn first(&self) -> Option<&[u8]> {
78 self.get(0)
79 }
80
81 pub fn iter(&self) -> impl Iterator<Item = &[u8]> {
83 (0..self.len()).map(move |i| self.get(i).expect("in range"))
84 }
85}
86
87impl core::ops::Index<usize> for Argv {
88 type Output = [u8];
89 fn index(&self, i: usize) -> &[u8] {
90 self.get(i).expect("argv index out of bounds")
91 }
92}
93
94impl PartialEq<Vec<Vec<u8>>> for Argv {
97 fn eq(&self, other: &Vec<Vec<u8>>) -> bool {
98 self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b.as_slice())
99 }
100}
101
102impl PartialEq for Argv {
103 fn eq(&self, other: &Argv) -> bool {
104 self.buf == other.buf && self.ends == other.ends
105 }
106}
107
108impl From<Vec<Vec<u8>>> for Argv {
112 fn from(v: Vec<Vec<u8>>) -> Self {
113 let mut a = Argv::with_capacity(v.len(), v.iter().map(Vec::len).sum());
114 for arg in &v {
115 a.push(arg);
116 }
117 a
118 }
119}
120
121pub type Command = Argv;
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn with_capacity_preallocates_both_buffers() {
130 let a: Argv = Argv::with_capacity(4, 32);
131 assert_eq!(a.len(), 0);
132 assert!(a.is_empty());
133 assert!(a.buf.capacity() >= 32);
135 assert!(a.ends.capacity() >= 4);
136 }
137
138 #[test]
139 fn clear_keeps_capacity_resets_len() {
140 let mut a = Argv::default();
141 a.push(b"foo");
142 a.push(b"barbaz");
143 assert_eq!(a.len(), 2);
144 let cap_buf = a.buf.capacity();
145 let cap_ends = a.ends.capacity();
146 a.clear();
147 assert_eq!(a.len(), 0);
148 assert!(a.is_empty());
149 assert_eq!(a.buf.capacity(), cap_buf);
151 assert_eq!(a.ends.capacity(), cap_ends);
152 }
153
154 #[test]
155 fn reserve_for_grows_to_at_least_requested() {
156 let mut a = Argv::with_capacity(1, 4);
157 a.reserve_for(8, 64);
158 assert!(a.buf.capacity() >= 64);
159 assert!(a.ends.capacity() >= 8);
160 a.reserve_for(0, 0);
162 assert!(a.buf.capacity() >= 64);
163 assert!(a.ends.capacity() >= 8);
164 }
165
166 #[test]
167 fn push_get_iter_first_round_trip() {
168 let mut a = Argv::default();
169 a.push(b"SET");
170 a.push(b"key");
171 a.push(b"value");
172 assert_eq!(a.len(), 3);
173 assert_eq!(a.first(), Some(b"SET" as &[u8]));
174 assert_eq!(a.get(0), Some(b"SET" as &[u8]));
175 assert_eq!(a.get(1), Some(b"key" as &[u8]));
176 assert_eq!(a.get(2), Some(b"value" as &[u8]));
177 assert_eq!(a.get(3), None);
178 let collected: Vec<&[u8]> = a.iter().collect();
179 assert_eq!(collected, vec![b"SET" as &[u8], b"key", b"value"]);
180 }
181
182 #[test]
183 fn first_on_empty_returns_none() {
184 let a = Argv::default();
185 assert_eq!(a.first(), None);
186 assert_eq!(a.get(0), None);
187 }
188
189 #[test]
190 fn index_returns_correct_slice() {
191 let mut a = Argv::default();
192 a.push(b"hi");
193 a.push(b"there");
194 assert_eq!(&a[0], b"hi" as &[u8]);
195 assert_eq!(&a[1], b"there" as &[u8]);
196 }
197
198 #[test]
199 #[should_panic(expected = "argv index out of bounds")]
200 fn index_out_of_bounds_panics() {
201 let a = Argv::default();
202 let _ = &a[0];
203 }
204
205 #[test]
206 fn eq_against_vec_of_vec() {
207 let mut a = Argv::default();
208 a.push(b"PING");
209 a.push(b"hello");
210 assert_eq!(a, vec![b"PING".to_vec(), b"hello".to_vec()]);
211 assert_ne!(a, vec![b"PING".to_vec()]);
212 assert_ne!(a, vec![b"PING".to_vec(), b"world".to_vec()]);
213 }
214
215 #[test]
216 fn eq_argv_vs_argv() {
217 let mut a = Argv::default();
218 a.push(b"A");
219 a.push(b"B");
220 let mut b = Argv::default();
221 b.push(b"A");
222 b.push(b"B");
223 let mut c = Argv::default();
224 c.push(b"A");
225 c.push(b"C");
226 assert_eq!(a, b);
227 assert_ne!(a, c);
228 }
229
230 #[test]
231 fn from_vec_of_vec_preserves_args() {
232 let v = vec![b"GET".to_vec(), b"my-key".to_vec()];
233 let a: Argv = Argv::from(v.clone());
234 assert_eq!(a.len(), 2);
235 assert_eq!(a, v);
236 assert_eq!(a.buf.len(), 3 + 6);
238 }
239
240 #[test]
241 fn clone_makes_independent_argv() {
242 let mut a = Argv::default();
243 a.push(b"X");
244 let b = a.clone();
245 assert_eq!(a, b);
246 a.push(b"Y");
248 assert_ne!(a, b);
249 assert_eq!(b.len(), 1);
250 }
251}