]>
Commit | Line | Data |
---|---|---|
f2b60f7d | 1 | use super::{repeat, BorrowedBuf, Cursor, SeekFrom}; |
1b1a35ee | 2 | use crate::cmp::{self, min}; |
1b1a35ee | 3 | use crate::io::{self, IoSlice, IoSliceMut}; |
6a06907d | 4 | use crate::io::{BufRead, BufReader, Read, Seek, Write}; |
a2a8927a | 5 | use crate::mem::MaybeUninit; |
1b1a35ee XL |
6 | use crate::ops::Deref; |
7 | ||
8 | #[test] | |
9 | #[cfg_attr(target_os = "emscripten", ignore)] | |
10 | fn read_until() { | |
11 | let mut buf = Cursor::new(&b"12"[..]); | |
12 | let mut v = Vec::new(); | |
13 | assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); | |
14 | assert_eq!(v, b"12"); | |
15 | ||
16 | let mut buf = Cursor::new(&b"1233"[..]); | |
17 | let mut v = Vec::new(); | |
18 | assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); | |
19 | assert_eq!(v, b"123"); | |
20 | v.truncate(0); | |
21 | assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); | |
22 | assert_eq!(v, b"3"); | |
23 | v.truncate(0); | |
24 | assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); | |
25 | assert_eq!(v, []); | |
26 | } | |
27 | ||
4b012472 FG |
28 | #[test] |
29 | fn skip_until() { | |
30 | let bytes: &[u8] = b"read\0ignore\0read\0ignore\0read\0ignore\0"; | |
31 | let mut reader = BufReader::new(bytes); | |
32 | ||
33 | // read from the bytes, alternating between | |
34 | // consuming `read\0`s and skipping `ignore\0`s | |
35 | loop { | |
36 | // consume `read\0` | |
37 | let mut out = Vec::new(); | |
38 | let read = reader.read_until(0, &mut out).unwrap(); | |
39 | if read == 0 { | |
40 | // eof | |
41 | break; | |
42 | } else { | |
43 | assert_eq!(out, b"read\0"); | |
44 | assert_eq!(read, b"read\0".len()); | |
45 | } | |
46 | ||
47 | // skip past `ignore\0` | |
48 | let skipped = reader.skip_until(0).unwrap(); | |
49 | assert_eq!(skipped, b"ignore\0".len()); | |
50 | } | |
51 | ||
52 | // ensure we are at the end of the byte slice and that we can skip no further | |
53 | // also ensure skip_until matches the behavior of read_until at EOF | |
54 | let skipped = reader.skip_until(0).unwrap(); | |
55 | assert_eq!(skipped, 0); | |
56 | } | |
57 | ||
1b1a35ee XL |
58 | #[test] |
59 | fn split() { | |
60 | let buf = Cursor::new(&b"12"[..]); | |
61 | let mut s = buf.split(b'3'); | |
62 | assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); | |
63 | assert!(s.next().is_none()); | |
64 | ||
65 | let buf = Cursor::new(&b"1233"[..]); | |
66 | let mut s = buf.split(b'3'); | |
67 | assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); | |
68 | assert_eq!(s.next().unwrap().unwrap(), vec![]); | |
69 | assert!(s.next().is_none()); | |
70 | } | |
71 | ||
72 | #[test] | |
73 | fn read_line() { | |
74 | let mut buf = Cursor::new(&b"12"[..]); | |
75 | let mut v = String::new(); | |
76 | assert_eq!(buf.read_line(&mut v).unwrap(), 2); | |
77 | assert_eq!(v, "12"); | |
78 | ||
79 | let mut buf = Cursor::new(&b"12\n\n"[..]); | |
80 | let mut v = String::new(); | |
81 | assert_eq!(buf.read_line(&mut v).unwrap(), 3); | |
82 | assert_eq!(v, "12\n"); | |
83 | v.truncate(0); | |
84 | assert_eq!(buf.read_line(&mut v).unwrap(), 1); | |
85 | assert_eq!(v, "\n"); | |
86 | v.truncate(0); | |
87 | assert_eq!(buf.read_line(&mut v).unwrap(), 0); | |
88 | assert_eq!(v, ""); | |
89 | } | |
90 | ||
91 | #[test] | |
92 | fn lines() { | |
93 | let buf = Cursor::new(&b"12\r"[..]); | |
94 | let mut s = buf.lines(); | |
95 | assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string()); | |
96 | assert!(s.next().is_none()); | |
97 | ||
98 | let buf = Cursor::new(&b"12\r\n\n"[..]); | |
99 | let mut s = buf.lines(); | |
100 | assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); | |
101 | assert_eq!(s.next().unwrap().unwrap(), "".to_string()); | |
102 | assert!(s.next().is_none()); | |
103 | } | |
104 | ||
136023e0 XL |
105 | #[test] |
106 | fn buf_read_has_data_left() { | |
107 | let mut buf = Cursor::new(&b"abcd"[..]); | |
108 | assert!(buf.has_data_left().unwrap()); | |
109 | buf.read_exact(&mut [0; 2]).unwrap(); | |
110 | assert!(buf.has_data_left().unwrap()); | |
111 | buf.read_exact(&mut [0; 2]).unwrap(); | |
112 | assert!(!buf.has_data_left().unwrap()); | |
113 | } | |
114 | ||
1b1a35ee XL |
115 | #[test] |
116 | fn read_to_end() { | |
117 | let mut c = Cursor::new(&b""[..]); | |
118 | let mut v = Vec::new(); | |
119 | assert_eq!(c.read_to_end(&mut v).unwrap(), 0); | |
120 | assert_eq!(v, []); | |
121 | ||
122 | let mut c = Cursor::new(&b"1"[..]); | |
123 | let mut v = Vec::new(); | |
124 | assert_eq!(c.read_to_end(&mut v).unwrap(), 1); | |
125 | assert_eq!(v, b"1"); | |
126 | ||
f2b60f7d | 127 | let cap = if cfg!(miri) { 1024 } else { 1024 * 1024 }; |
1b1a35ee XL |
128 | let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>(); |
129 | let mut v = Vec::new(); | |
130 | let (a, b) = data.split_at(data.len() / 2); | |
131 | assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len()); | |
132 | assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len()); | |
133 | assert_eq!(v, data); | |
134 | } | |
135 | ||
136 | #[test] | |
137 | fn read_to_string() { | |
138 | let mut c = Cursor::new(&b""[..]); | |
139 | let mut v = String::new(); | |
140 | assert_eq!(c.read_to_string(&mut v).unwrap(), 0); | |
141 | assert_eq!(v, ""); | |
142 | ||
143 | let mut c = Cursor::new(&b"1"[..]); | |
144 | let mut v = String::new(); | |
145 | assert_eq!(c.read_to_string(&mut v).unwrap(), 1); | |
146 | assert_eq!(v, "1"); | |
147 | ||
148 | let mut c = Cursor::new(&b"\xff"[..]); | |
149 | let mut v = String::new(); | |
150 | assert!(c.read_to_string(&mut v).is_err()); | |
151 | } | |
152 | ||
153 | #[test] | |
154 | fn read_exact() { | |
155 | let mut buf = [0; 4]; | |
156 | ||
157 | let mut c = Cursor::new(&b""[..]); | |
158 | assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); | |
159 | ||
160 | let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..])); | |
161 | c.read_exact(&mut buf).unwrap(); | |
162 | assert_eq!(&buf, b"1234"); | |
163 | c.read_exact(&mut buf).unwrap(); | |
164 | assert_eq!(&buf, b"5678"); | |
165 | assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); | |
166 | } | |
167 | ||
168 | #[test] | |
169 | fn read_exact_slice() { | |
170 | let mut buf = [0; 4]; | |
171 | ||
172 | let mut c = &b""[..]; | |
173 | assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); | |
174 | ||
175 | let mut c = &b"123"[..]; | |
176 | assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); | |
177 | // make sure the optimized (early returning) method is being used | |
178 | assert_eq!(&buf, &[0; 4]); | |
179 | ||
180 | let mut c = &b"1234"[..]; | |
181 | c.read_exact(&mut buf).unwrap(); | |
182 | assert_eq!(&buf, b"1234"); | |
183 | ||
184 | let mut c = &b"56789"[..]; | |
185 | c.read_exact(&mut buf).unwrap(); | |
186 | assert_eq!(&buf, b"5678"); | |
187 | assert_eq!(c, b"9"); | |
188 | } | |
189 | ||
a2a8927a XL |
190 | #[test] |
191 | fn read_buf_exact() { | |
f2b60f7d FG |
192 | let buf: &mut [_] = &mut [0; 4]; |
193 | let mut buf: BorrowedBuf<'_> = buf.into(); | |
a2a8927a XL |
194 | |
195 | let mut c = Cursor::new(&b""[..]); | |
f2b60f7d | 196 | assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); |
a2a8927a XL |
197 | |
198 | let mut c = Cursor::new(&b"123456789"[..]); | |
f2b60f7d | 199 | c.read_buf_exact(buf.unfilled()).unwrap(); |
a2a8927a XL |
200 | assert_eq!(buf.filled(), b"1234"); |
201 | ||
202 | buf.clear(); | |
203 | ||
f2b60f7d | 204 | c.read_buf_exact(buf.unfilled()).unwrap(); |
a2a8927a XL |
205 | assert_eq!(buf.filled(), b"5678"); |
206 | ||
207 | buf.clear(); | |
208 | ||
f2b60f7d | 209 | assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); |
a2a8927a XL |
210 | } |
211 | ||
1b1a35ee XL |
212 | #[test] |
213 | fn take_eof() { | |
214 | struct R; | |
215 | ||
216 | impl Read for R { | |
217 | fn read(&mut self, _: &mut [u8]) -> io::Result<usize> { | |
5099ac24 | 218 | Err(io::const_io_error!(io::ErrorKind::Other, "")) |
1b1a35ee XL |
219 | } |
220 | } | |
221 | impl BufRead for R { | |
222 | fn fill_buf(&mut self) -> io::Result<&[u8]> { | |
5099ac24 | 223 | Err(io::const_io_error!(io::ErrorKind::Other, "")) |
1b1a35ee XL |
224 | } |
225 | fn consume(&mut self, _amt: usize) {} | |
226 | } | |
227 | ||
228 | let mut buf = [0; 1]; | |
229 | assert_eq!(0, R.take(0).read(&mut buf).unwrap()); | |
230 | assert_eq!(b"", R.take(0).fill_buf().unwrap()); | |
231 | } | |
232 | ||
233 | fn cmp_bufread<Br1: BufRead, Br2: BufRead>(mut br1: Br1, mut br2: Br2, exp: &[u8]) { | |
234 | let mut cat = Vec::new(); | |
235 | loop { | |
236 | let consume = { | |
237 | let buf1 = br1.fill_buf().unwrap(); | |
238 | let buf2 = br2.fill_buf().unwrap(); | |
239 | let minlen = if buf1.len() < buf2.len() { buf1.len() } else { buf2.len() }; | |
240 | assert_eq!(buf1[..minlen], buf2[..minlen]); | |
241 | cat.extend_from_slice(&buf1[..minlen]); | |
242 | minlen | |
243 | }; | |
244 | if consume == 0 { | |
245 | break; | |
246 | } | |
247 | br1.consume(consume); | |
248 | br2.consume(consume); | |
249 | } | |
250 | assert_eq!(br1.fill_buf().unwrap().len(), 0); | |
251 | assert_eq!(br2.fill_buf().unwrap().len(), 0); | |
252 | assert_eq!(&cat[..], &exp[..]) | |
253 | } | |
254 | ||
255 | #[test] | |
256 | fn chain_bufread() { | |
257 | let testdata = b"ABCDEFGHIJKL"; | |
258 | let chain1 = | |
259 | (&testdata[..3]).chain(&testdata[3..6]).chain(&testdata[6..9]).chain(&testdata[9..]); | |
260 | let chain2 = (&testdata[..4]).chain(&testdata[4..8]).chain(&testdata[8..]); | |
261 | cmp_bufread(chain1, chain2, &testdata[..]); | |
262 | } | |
263 | ||
6a06907d XL |
264 | #[test] |
265 | fn bufreader_size_hint() { | |
266 | let testdata = b"ABCDEFGHIJKL"; | |
267 | let mut buf_reader = BufReader::new(&testdata[..]); | |
268 | assert_eq!(buf_reader.buffer().len(), 0); | |
269 | ||
270 | let buffer_length = testdata.len(); | |
271 | buf_reader.fill_buf().unwrap(); | |
272 | ||
273 | // Check that size hint matches buffer contents | |
274 | let mut buffered_bytes = buf_reader.bytes(); | |
275 | let (lower_bound, _upper_bound) = buffered_bytes.size_hint(); | |
276 | assert_eq!(lower_bound, buffer_length); | |
277 | ||
278 | // Check that size hint matches buffer contents after advancing | |
279 | buffered_bytes.next().unwrap().unwrap(); | |
280 | let (lower_bound, _upper_bound) = buffered_bytes.size_hint(); | |
281 | assert_eq!(lower_bound, buffer_length - 1); | |
282 | } | |
283 | ||
284 | #[test] | |
285 | fn empty_size_hint() { | |
286 | let size_hint = io::empty().bytes().size_hint(); | |
287 | assert_eq!(size_hint, (0, Some(0))); | |
288 | } | |
289 | ||
136023e0 XL |
290 | #[test] |
291 | fn slice_size_hint() { | |
292 | let size_hint = (&[1, 2, 3]).bytes().size_hint(); | |
293 | assert_eq!(size_hint, (3, Some(3))); | |
294 | } | |
295 | ||
296 | #[test] | |
297 | fn take_size_hint() { | |
298 | let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint(); | |
299 | assert_eq!(size_hint, (2, Some(2))); | |
300 | ||
301 | let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint(); | |
302 | assert_eq!(size_hint, (3, Some(3))); | |
303 | ||
304 | let size_hint = io::repeat(0).take(3).bytes().size_hint(); | |
305 | assert_eq!(size_hint, (3, Some(3))); | |
306 | } | |
307 | ||
6a06907d XL |
308 | #[test] |
309 | fn chain_empty_size_hint() { | |
310 | let chain = io::empty().chain(io::empty()); | |
311 | let size_hint = chain.bytes().size_hint(); | |
312 | assert_eq!(size_hint, (0, Some(0))); | |
313 | } | |
314 | ||
315 | #[test] | |
316 | fn chain_size_hint() { | |
317 | let testdata = b"ABCDEFGHIJKL"; | |
318 | let mut buf_reader_1 = BufReader::new(&testdata[..6]); | |
319 | let mut buf_reader_2 = BufReader::new(&testdata[6..]); | |
320 | ||
321 | buf_reader_1.fill_buf().unwrap(); | |
322 | buf_reader_2.fill_buf().unwrap(); | |
323 | ||
324 | let chain = buf_reader_1.chain(buf_reader_2); | |
325 | let size_hint = chain.bytes().size_hint(); | |
136023e0 | 326 | assert_eq!(size_hint, (testdata.len(), Some(testdata.len()))); |
6a06907d XL |
327 | } |
328 | ||
1b1a35ee XL |
329 | #[test] |
330 | fn chain_zero_length_read_is_not_eof() { | |
331 | let a = b"A"; | |
332 | let b = b"B"; | |
333 | let mut s = String::new(); | |
334 | let mut chain = (&a[..]).chain(&b[..]); | |
335 | chain.read(&mut []).unwrap(); | |
336 | chain.read_to_string(&mut s).unwrap(); | |
337 | assert_eq!("AB", s); | |
338 | } | |
339 | ||
340 | #[bench] | |
341 | #[cfg_attr(target_os = "emscripten", ignore)] | |
f2b60f7d | 342 | #[cfg_attr(miri, ignore)] // Miri isn't fast... |
1b1a35ee XL |
343 | fn bench_read_to_end(b: &mut test::Bencher) { |
344 | b.iter(|| { | |
345 | let mut lr = repeat(1).take(10000000); | |
346 | let mut vec = Vec::with_capacity(1024); | |
49aad941 | 347 | super::default_read_to_end(&mut lr, &mut vec, None) |
1b1a35ee XL |
348 | }); |
349 | } | |
350 | ||
351 | #[test] | |
352 | fn seek_len() -> io::Result<()> { | |
353 | let mut c = Cursor::new(vec![0; 15]); | |
354 | assert_eq!(c.stream_len()?, 15); | |
355 | ||
356 | c.seek(SeekFrom::End(0))?; | |
357 | let old_pos = c.stream_position()?; | |
358 | assert_eq!(c.stream_len()?, 15); | |
359 | assert_eq!(c.stream_position()?, old_pos); | |
360 | ||
361 | c.seek(SeekFrom::Start(7))?; | |
362 | c.seek(SeekFrom::Current(2))?; | |
363 | let old_pos = c.stream_position()?; | |
364 | assert_eq!(c.stream_len()?, 15); | |
365 | assert_eq!(c.stream_position()?, old_pos); | |
366 | ||
367 | Ok(()) | |
368 | } | |
369 | ||
370 | #[test] | |
371 | fn seek_position() -> io::Result<()> { | |
372 | // All `asserts` are duplicated here to make sure the method does not | |
373 | // change anything about the seek state. | |
374 | let mut c = Cursor::new(vec![0; 15]); | |
375 | assert_eq!(c.stream_position()?, 0); | |
376 | assert_eq!(c.stream_position()?, 0); | |
377 | ||
378 | c.seek(SeekFrom::End(0))?; | |
379 | assert_eq!(c.stream_position()?, 15); | |
380 | assert_eq!(c.stream_position()?, 15); | |
381 | ||
382 | c.seek(SeekFrom::Start(7))?; | |
383 | c.seek(SeekFrom::Current(2))?; | |
384 | assert_eq!(c.stream_position()?, 9); | |
385 | assert_eq!(c.stream_position()?, 9); | |
386 | ||
387 | c.seek(SeekFrom::End(-3))?; | |
388 | c.seek(SeekFrom::Current(1))?; | |
389 | c.seek(SeekFrom::Current(-5))?; | |
390 | assert_eq!(c.stream_position()?, 8); | |
391 | assert_eq!(c.stream_position()?, 8); | |
392 | ||
136023e0 XL |
393 | c.rewind()?; |
394 | assert_eq!(c.stream_position()?, 0); | |
395 | assert_eq!(c.stream_position()?, 0); | |
396 | ||
1b1a35ee XL |
397 | Ok(()) |
398 | } | |
399 | ||
400 | // A simple example reader which uses the default implementation of | |
401 | // read_to_end. | |
402 | struct ExampleSliceReader<'a> { | |
403 | slice: &'a [u8], | |
404 | } | |
405 | ||
406 | impl<'a> Read for ExampleSliceReader<'a> { | |
407 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
408 | let len = cmp::min(self.slice.len(), buf.len()); | |
409 | buf[..len].copy_from_slice(&self.slice[..len]); | |
410 | self.slice = &self.slice[len..]; | |
411 | Ok(len) | |
412 | } | |
413 | } | |
414 | ||
415 | #[test] | |
416 | fn test_read_to_end_capacity() -> io::Result<()> { | |
417 | let input = &b"foo"[..]; | |
418 | ||
c295e0f8 XL |
419 | // read_to_end() takes care not to over-allocate when a buffer is the |
420 | // exact size needed. | |
1b1a35ee XL |
421 | let mut vec1 = Vec::with_capacity(input.len()); |
422 | ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; | |
423 | assert_eq!(vec1.len(), input.len()); | |
c295e0f8 | 424 | assert_eq!(vec1.capacity(), input.len(), "did not allocate more"); |
1b1a35ee XL |
425 | |
426 | Ok(()) | |
427 | } | |
428 | ||
429 | #[test] | |
136023e0 | 430 | fn io_slice_mut_advance_slices() { |
1b1a35ee XL |
431 | let mut buf1 = [1; 8]; |
432 | let mut buf2 = [2; 16]; | |
433 | let mut buf3 = [3; 8]; | |
434 | let mut bufs = &mut [ | |
435 | IoSliceMut::new(&mut buf1), | |
436 | IoSliceMut::new(&mut buf2), | |
437 | IoSliceMut::new(&mut buf3), | |
438 | ][..]; | |
439 | ||
440 | // Only in a single buffer.. | |
136023e0 | 441 | IoSliceMut::advance_slices(&mut bufs, 1); |
1b1a35ee XL |
442 | assert_eq!(bufs[0].deref(), [1; 7].as_ref()); |
443 | assert_eq!(bufs[1].deref(), [2; 16].as_ref()); | |
444 | assert_eq!(bufs[2].deref(), [3; 8].as_ref()); | |
445 | ||
446 | // Removing a buffer, leaving others as is. | |
136023e0 | 447 | IoSliceMut::advance_slices(&mut bufs, 7); |
1b1a35ee XL |
448 | assert_eq!(bufs[0].deref(), [2; 16].as_ref()); |
449 | assert_eq!(bufs[1].deref(), [3; 8].as_ref()); | |
450 | ||
451 | // Removing a buffer and removing from the next buffer. | |
136023e0 | 452 | IoSliceMut::advance_slices(&mut bufs, 18); |
1b1a35ee XL |
453 | assert_eq!(bufs[0].deref(), [3; 6].as_ref()); |
454 | } | |
455 | ||
456 | #[test] | |
923072b8 | 457 | #[should_panic] |
136023e0 XL |
458 | fn io_slice_mut_advance_slices_empty_slice() { |
459 | let mut empty_bufs = &mut [][..]; | |
136023e0 | 460 | IoSliceMut::advance_slices(&mut empty_bufs, 1); |
1b1a35ee XL |
461 | } |
462 | ||
463 | #[test] | |
923072b8 | 464 | #[should_panic] |
136023e0 | 465 | fn io_slice_mut_advance_slices_beyond_total_length() { |
1b1a35ee XL |
466 | let mut buf1 = [1; 8]; |
467 | let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; | |
468 | ||
136023e0 | 469 | IoSliceMut::advance_slices(&mut bufs, 9); |
1b1a35ee XL |
470 | assert!(bufs.is_empty()); |
471 | } | |
472 | ||
473 | #[test] | |
136023e0 | 474 | fn io_slice_advance_slices() { |
1b1a35ee XL |
475 | let buf1 = [1; 8]; |
476 | let buf2 = [2; 16]; | |
477 | let buf3 = [3; 8]; | |
478 | let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..]; | |
479 | ||
480 | // Only in a single buffer.. | |
136023e0 | 481 | IoSlice::advance_slices(&mut bufs, 1); |
1b1a35ee XL |
482 | assert_eq!(bufs[0].deref(), [1; 7].as_ref()); |
483 | assert_eq!(bufs[1].deref(), [2; 16].as_ref()); | |
484 | assert_eq!(bufs[2].deref(), [3; 8].as_ref()); | |
485 | ||
486 | // Removing a buffer, leaving others as is. | |
136023e0 | 487 | IoSlice::advance_slices(&mut bufs, 7); |
1b1a35ee XL |
488 | assert_eq!(bufs[0].deref(), [2; 16].as_ref()); |
489 | assert_eq!(bufs[1].deref(), [3; 8].as_ref()); | |
490 | ||
491 | // Removing a buffer and removing from the next buffer. | |
136023e0 | 492 | IoSlice::advance_slices(&mut bufs, 18); |
1b1a35ee XL |
493 | assert_eq!(bufs[0].deref(), [3; 6].as_ref()); |
494 | } | |
495 | ||
496 | #[test] | |
923072b8 | 497 | #[should_panic] |
136023e0 XL |
498 | fn io_slice_advance_slices_empty_slice() { |
499 | let mut empty_bufs = &mut [][..]; | |
136023e0 | 500 | IoSlice::advance_slices(&mut empty_bufs, 1); |
1b1a35ee XL |
501 | } |
502 | ||
503 | #[test] | |
923072b8 | 504 | #[should_panic] |
136023e0 | 505 | fn io_slice_advance_slices_beyond_total_length() { |
1b1a35ee XL |
506 | let buf1 = [1; 8]; |
507 | let mut bufs = &mut [IoSlice::new(&buf1)][..]; | |
508 | ||
136023e0 | 509 | IoSlice::advance_slices(&mut bufs, 9); |
1b1a35ee XL |
510 | assert!(bufs.is_empty()); |
511 | } | |
512 | ||
513 | /// Create a new writer that reads from at most `n_bufs` and reads | |
514 | /// `per_call` bytes (in total) per call to write. | |
515 | fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter { | |
516 | TestWriter { n_bufs, per_call, written: Vec::new() } | |
517 | } | |
518 | ||
519 | struct TestWriter { | |
520 | n_bufs: usize, | |
521 | per_call: usize, | |
522 | written: Vec<u8>, | |
523 | } | |
524 | ||
525 | impl Write for TestWriter { | |
526 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
527 | self.write_vectored(&[IoSlice::new(buf)]) | |
528 | } | |
529 | ||
530 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { | |
531 | let mut left = self.per_call; | |
532 | let mut written = 0; | |
533 | for buf in bufs.iter().take(self.n_bufs) { | |
534 | let n = min(left, buf.len()); | |
535 | self.written.extend_from_slice(&buf[0..n]); | |
536 | left -= n; | |
537 | written += n; | |
538 | } | |
539 | Ok(written) | |
540 | } | |
541 | ||
542 | fn flush(&mut self) -> io::Result<()> { | |
543 | Ok(()) | |
544 | } | |
545 | } | |
546 | ||
547 | #[test] | |
548 | fn test_writer_read_from_one_buf() { | |
549 | let mut writer = test_writer(1, 2); | |
550 | ||
551 | assert_eq!(writer.write(&[]).unwrap(), 0); | |
552 | assert_eq!(writer.write_vectored(&[]).unwrap(), 0); | |
553 | ||
554 | // Read at most 2 bytes. | |
555 | assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2); | |
556 | let bufs = &[IoSlice::new(&[2, 2, 2])]; | |
557 | assert_eq!(writer.write_vectored(bufs).unwrap(), 2); | |
558 | ||
559 | // Only read from first buf. | |
560 | let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])]; | |
561 | assert_eq!(writer.write_vectored(bufs).unwrap(), 1); | |
562 | ||
563 | assert_eq!(writer.written, &[1, 1, 2, 2, 3]); | |
564 | } | |
565 | ||
566 | #[test] | |
567 | fn test_writer_read_from_multiple_bufs() { | |
568 | let mut writer = test_writer(3, 3); | |
569 | ||
570 | // Read at most 3 bytes from two buffers. | |
571 | let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])]; | |
572 | assert_eq!(writer.write_vectored(bufs).unwrap(), 3); | |
573 | ||
574 | // Read at most 3 bytes from three buffers. | |
575 | let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])]; | |
576 | assert_eq!(writer.write_vectored(bufs).unwrap(), 3); | |
577 | ||
578 | assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]); | |
579 | } | |
580 | ||
581 | #[test] | |
582 | fn test_write_all_vectored() { | |
583 | #[rustfmt::skip] // Becomes unreadable otherwise. | |
584 | let tests: Vec<(_, &'static [u8])> = vec![ | |
585 | (vec![], &[]), | |
586 | (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]), | |
587 | (vec![IoSlice::new(&[1])], &[1]), | |
588 | (vec![IoSlice::new(&[1, 2])], &[1, 2]), | |
589 | (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]), | |
590 | (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]), | |
591 | (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]), | |
592 | (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]), | |
593 | (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]), | |
594 | (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]), | |
595 | (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), | |
596 | (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), | |
597 | (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]), | |
598 | (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]), | |
599 | (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]), | |
600 | (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]), | |
601 | (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]), | |
602 | (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]), | |
603 | (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]), | |
604 | ]; | |
605 | ||
606 | let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]; | |
607 | ||
608 | for (n_bufs, per_call) in writer_configs.iter().copied() { | |
609 | for (mut input, wanted) in tests.clone().into_iter() { | |
610 | let mut writer = test_writer(n_bufs, per_call); | |
611 | assert!(writer.write_all_vectored(&mut *input).is_ok()); | |
612 | assert_eq!(&*writer.written, &*wanted); | |
613 | } | |
614 | } | |
615 | } | |
a2a8927a | 616 | |
064997fb FG |
617 | // Issue 94981 |
618 | #[test] | |
619 | #[should_panic = "number of read bytes exceeds limit"] | |
620 | fn test_take_wrong_length() { | |
621 | struct LieAboutSize(bool); | |
622 | ||
623 | impl Read for LieAboutSize { | |
624 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
625 | // Lie about the read size at first time of read. | |
626 | if core::mem::take(&mut self.0) { Ok(buf.len() + 1) } else { Ok(buf.len()) } | |
627 | } | |
628 | } | |
629 | ||
630 | let mut buffer = vec![0; 4]; | |
631 | let mut reader = LieAboutSize(true).take(4); | |
632 | // Primed the `Limit` by lying about the read size. | |
633 | let _ = reader.read(&mut buffer[..]); | |
634 | } | |
635 | ||
a2a8927a XL |
636 | #[bench] |
637 | fn bench_take_read(b: &mut test::Bencher) { | |
638 | b.iter(|| { | |
639 | let mut buf = [0; 64]; | |
640 | ||
641 | [255; 128].take(64).read(&mut buf).unwrap(); | |
642 | }); | |
643 | } | |
644 | ||
645 | #[bench] | |
646 | fn bench_take_read_buf(b: &mut test::Bencher) { | |
647 | b.iter(|| { | |
f2b60f7d | 648 | let buf: &mut [_] = &mut [MaybeUninit::uninit(); 64]; |
a2a8927a | 649 | |
f2b60f7d | 650 | let mut buf: BorrowedBuf<'_> = buf.into(); |
a2a8927a | 651 | |
f2b60f7d | 652 | [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
653 | }); |
654 | } |