1use std::fmt::Debug;
2
3pub trait ParseHelper: AsRef<[u8]> {
5 fn take_until(&self, pattern: &[u8]) -> Result<(&[u8], &[u8]), ()> {
7 let source = self.as_ref();
8 if source.len() < pattern.len() {
9 return Err(());
10 }
11 for i in 0..=source.len() - pattern.len() {
12 if source[i..].starts_with(pattern) {
13 return Ok((&source[..i], &source[i..]));
14 }
15 }
16 Err(())
17 }
18
19 fn take_until_err<E: Debug>(&self, pattern: &[u8], err: E) -> Result<(&[u8], &[u8]), E> {
21 self.take_until(pattern).map_err(|_| err)
22 }
23
24 fn take_exact(&self, count: usize) -> Result<(&[u8], &[u8]), ()> {
26 let source = self.as_ref();
27 if source.len() < count {
28 return Err(());
29 }
30 Ok((&source[..count], &source[count..]))
31 }
32
33 fn take_exact_err<E: Debug>(&self, count: usize, err: E) -> Result<(&[u8], &[u8]), E> {
35 self.take_exact(count).map_err(|_| err)
36 }
37
38 fn take_expect(&self, pattern: &[u8]) -> Result<(&[u8], &[u8]), &[u8]> {
40 let source = self.as_ref();
41 if source.len() < pattern.len() {
42 return Err(source);
43 }
44 for i in 0..pattern.len() {
45 if source[i] != pattern[i] {
46 return Err(source);
47 }
48 }
49 Ok((&source[..pattern.len()], &source[pattern.len()..]))
50 }
51
52 fn take_expect_err<E: Debug>(&self, pattern: &[u8], err: E) -> Result<(&[u8], &[u8]), E> {
54 self.take_expect(pattern).map_err(|_| err)
55 }
56
57 fn maybe_expect(&self, pattern: &[u8]) -> (Option<&[u8]>, &[u8]) {
59 match self.take_expect(pattern) {
60 Ok((first, second)) => (Some(first), second),
61 Err(_) => (None, self.as_ref())
62 }
63 }
64
65 fn take_smallest_err<E: Debug, F: Fn(&[u8]) -> bool>(&self, f: F, min_size: usize, err: E) -> Result<(&[u8], &[u8]), E> {
68 for i in min_size..self.as_ref().len() {
69 if f(&self.as_ref()[..i]) {
70 return Ok((&self.as_ref()[..i], &self.as_ref()[i..]))
71 }
72 }
73 Err(err)
74 }
75
76 fn take_largest_err<E: Debug, F: Fn(&[u8]) -> bool>(&self, f: F, min_size:usize, err: E) -> Result<(&[u8], &[u8]), E> {
79 let mut largest = None;
80 for i in min_size..self.as_ref().len() {
81 if f(&self.as_ref()[..i]) {
82 largest = Some(i);
83 }
84 };
85 largest.map(|i| (&self.as_ref()[..i], &self.as_ref()[i..])).ok_or(err)
86 }
87}
88
89impl ParseHelper for &[u8] {}
90impl ParseHelper for [u8] {}
91impl ParseHelper for Vec<u8> {}
92impl ParseHelper for &str {}
93
94#[cfg(test)]
95mod test {
96 use crate::ParseHelper;
97
98 #[test]
99 fn test_take_until() {
100 let source = b"hello world";
101 let pattern = b" ";
102 let (before, after) = source.take_until(pattern).unwrap();
103 assert_eq!(before, b"hello");
104 assert_eq!(after, b" world");
105
106 let (before,after) = "GET / HTTP/1.1\r\n\r\n".take_until(b"\r\n\r\n").unwrap();
107 assert_eq!(before, b"GET / HTTP/1.1");
108 assert_eq!(after, b"\r\n\r\n");
109 }
110
111 #[test]
112 fn take_exact() {
113 let source = b"hello world";
114 let (exact, after) = source.take_exact(5).unwrap();
115 assert_eq!(exact, b"hello");
116 assert_eq!(after, b" world");
117 }
118
119 #[test]
120 fn take_expect() {
121 let source = b"hello world";
122 let (matching, remained) = source.take_expect(b"hello ").unwrap();
123 assert_eq!(matching, b"hello ");
124 assert_eq!(remained, b"world");
125 }
126
127 #[test]
128 fn take_smallest() {
129 let source = b"aaaabbbbcccc";
130 assert!(source.take_smallest_err(|s| s.starts_with(b"bbbb"), 0, ()).is_err());
131
132 let (first ,second) = source.take_smallest_err(|s| !s.contains(&b"b"[0]), 0, ()).unwrap();
133 assert_eq!(first, b"a");
134 assert_eq!(second, b"aaabbbbcccc");
135 }
136
137 #[test]
138 fn take_largest() {
139 let source = b"aaaabbbbcccc";
140
141 let func = |s: &[u8]| s.starts_with(b"b");
142 assert!(source.take_largest_err(func, 0, ()).is_err());
143
144 let func = |s: &[u8]| !s.contains(&b"b"[0]);
145 let (first, second) = source.take_largest_err(func, 0, ()).unwrap();
146 assert_eq!(first, b"aaaa");
147 assert_eq!(second, b"bbbbcccc");
148 }
149}