ipld_car/bounded_reader/
functions.rs1use crate::bounded_reader::traits::{Bounded, BoundedIndex, CloneAndRewind};
2use std::{io::Read, ops::RangeInclusive};
3
4pub fn slice_ref<R>(reader: R, pattern: &[u8]) -> Option<R>
5where
6 R: Read + CloneAndRewind + Bounded,
7 RangeInclusive<u64>: BoundedIndex<R>,
8{
9 if pattern.is_empty() {
10 return None;
11 }
12
13 const BUF_SIZE: usize = 4096;
14 let mut buf = [0u8; BUF_SIZE];
15
16 let last_reader_pos = reader.bound_len().saturating_sub(pattern.len() as u64 - 1);
17 let mut reader_pos = 0u64;
18 let mut pattern_pos = 0usize;
19
20 let mut src = reader.clone_and_rewind();
21 loop {
22 let n = match src.read(&mut buf) {
23 Ok(0) | Err(_) => break,
24 Ok(n) => n,
25 };
26 for &byte in &buf[..n] {
27 if reader_pos > last_reader_pos && pattern_pos == 0 {
28 return None;
29 }
30
31 if byte == pattern[pattern_pos] {
32 pattern_pos += 1;
33 if pattern_pos >= pattern.len() {
34 let start = reader_pos.saturating_sub(pattern.len() as u64 - 1);
35 return Some(reader.clamped_sub(start..=reader_pos));
36 }
37 } else {
38 pattern_pos = 0;
39 }
40
41 reader_pos += 1;
42 }
43 }
44
45 None
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::bounded_reader::sync::BoundedReader;
52
53 use anyhow::Result;
54 use std::io::{self, Cursor};
55 use test_case::case;
56
57 #[case( b"Hello world!!!", b"world", Some(b"world"); "middle")]
58 #[case( b"Hello world!!!", b"Hello", Some(b"Hello"); "begin")]
59 #[case( b"Hello world!!!", b"ld!!!", Some(b"ld!!!"); "end")]
60 #[case( b"Hello world!!!", b"universe", None; "none")]
61 fn slice_ref_test(data: &[u8], pattern: &[u8], exp_slice: Option<&[u8]>) -> Result<()> {
62 let reader = BoundedReader::from_reader(Cursor::new(data))?;
63 let slice = slice_ref(reader, pattern)
64 .map(|mut sliced_reader| {
65 let mut content = Vec::<u8>::with_capacity(sliced_reader.bound_len() as usize);
66 sliced_reader.read_to_end(&mut content)?;
67 Ok::<_, io::Error>(content)
68 })
69 .transpose()?;
70
71 assert_eq!(slice.as_deref(), exp_slice);
72 Ok(())
73 }
74}