1use std::io;
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use memchr::memchr;
5
6use super::{Decoder, Encoder};
7
8#[derive(Debug, Copy, Clone)]
20#[non_exhaustive]
21pub struct LinesCodec {
22 max_length: usize,
23 next_index: usize,
25}
26
27impl LinesCodec {
28 pub const fn new() -> Self {
32 Self {
33 max_length: usize::MAX,
34 next_index: 0,
35 }
36 }
37
38 pub const fn new_with_max_length(max_length: usize) -> Self {
46 Self {
47 max_length,
48 next_index: 0,
49 }
50 }
51
52 pub const fn max_length(&self) -> usize {
54 self.max_length
55 }
56}
57
58impl Default for LinesCodec {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl<T: AsRef<str>> Encoder<T> for LinesCodec {
65 type Error = io::Error;
66
67 #[inline]
68 fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error> {
69 let item = item.as_ref();
70 dst.reserve(item.len() + 1);
71 dst.put_slice(item.as_bytes());
72 dst.put_u8(b'\n');
73 Ok(())
74 }
75}
76
77impl Decoder for LinesCodec {
78 type Item = String;
79 type Error = io::Error;
80
81 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
82 if src.is_empty() {
83 self.next_index = 0;
84 return Ok(None);
85 }
86
87 let start = if self.next_index < src.len() {
90 self.next_index
91 } else {
92 0
93 };
94
95 let len = match memchr(b'\n', &src[start..]) {
96 Some(n) => start + n,
97 None => {
98 let max = self.max_length;
99 if max != usize::MAX {
100 let max_cr = max.saturating_add(1);
103
104 if src.len() > max && !(src.len() == max_cr && src.last() == Some(&b'\r')) {
105 return Err(io::Error::new(
106 io::ErrorKind::InvalidData,
107 "max line length exceeded",
108 ));
109 }
110 }
111
112 self.next_index = src.len();
113 return Ok(None);
114 }
115 };
116
117 let max = self.max_length;
119 if max != usize::MAX {
120 let max_cr = max.saturating_add(1);
121
122 if len > max && !(len == max_cr && src.get(len - 1) == Some(&b'\r')) {
123 return Err(io::Error::new(
124 io::ErrorKind::InvalidData,
125 "max line length exceeded",
126 ));
127 }
128 }
129
130 self.next_index = 0;
131
132 let mut buf = src.split_to(len);
134 debug_assert_eq!(len, buf.len());
135
136 src.advance(1);
138
139 match buf.last() {
140 Some(b'\r') => buf.truncate(len - 1),
142
143 None => return Ok(Some(String::new())),
145
146 _ => {}
147 }
148
149 try_into_utf8(buf.freeze())
150 }
151
152 fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
153 match self.decode(src)? {
154 Some(frame) => Ok(Some(frame)),
155 None if src.is_empty() => Ok(None),
156 None => {
157 self.next_index = 0;
158
159 let buf = match src.last() {
160 Some(b'\r') => src.split_to(src.len() - 1),
162
163 _ => src.split(),
165 };
166
167 if buf.is_empty() {
168 return Ok(None);
169 }
170
171 try_into_utf8(buf.freeze())
172 }
173 }
174 }
175}
176
177fn try_into_utf8(buf: Bytes) -> io::Result<Option<String>> {
179 String::from_utf8(buf.to_vec())
180 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
181 .map(Some)
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn lines_decoder() {
190 let mut codec = LinesCodec::default();
191 let mut buf = BytesMut::from("\nline 1\nline 2\r\nline 3\n\r\n\r");
192
193 assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
194 assert_eq!("line 1", codec.decode(&mut buf).unwrap().unwrap());
195 assert_eq!("line 2", codec.decode(&mut buf).unwrap().unwrap());
196 assert_eq!("line 3", codec.decode(&mut buf).unwrap().unwrap());
197 assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
198 assert!(codec.decode(&mut buf).unwrap().is_none());
199 assert!(codec.decode_eof(&mut buf).unwrap().is_none());
200
201 buf.put_slice(b"k");
202 assert!(codec.decode(&mut buf).unwrap().is_none());
203 assert_eq!("\rk", codec.decode_eof(&mut buf).unwrap().unwrap());
204
205 assert!(codec.decode(&mut buf).unwrap().is_none());
206 assert!(codec.decode_eof(&mut buf).unwrap().is_none());
207 }
208
209 #[test]
210 fn lines_encoder() {
211 let mut codec = LinesCodec::default();
212
213 let mut buf = BytesMut::new();
214
215 codec.encode("", &mut buf).unwrap();
216 assert_eq!(&buf[..], b"\n");
217
218 codec.encode("test", &mut buf).unwrap();
219 assert_eq!(&buf[..], b"\ntest\n");
220
221 codec.encode("a\nb", &mut buf).unwrap();
222 assert_eq!(&buf[..], b"\ntest\na\nb\n");
223 }
224
225 #[test]
226 fn lines_encoder_no_overflow() {
227 let mut codec = LinesCodec::default();
228
229 let mut buf = BytesMut::new();
230 codec.encode("1234567", &mut buf).unwrap();
231 assert_eq!(&buf[..], b"1234567\n");
232
233 let mut buf = BytesMut::new();
234 codec.encode("12345678", &mut buf).unwrap();
235 assert_eq!(&buf[..], b"12345678\n");
236
237 let mut buf = BytesMut::new();
238 codec.encode("123456789111213", &mut buf).unwrap();
239 assert_eq!(&buf[..], b"123456789111213\n");
240
241 let mut buf = BytesMut::new();
242 codec.encode("1234567891112131", &mut buf).unwrap();
243 assert_eq!(&buf[..], b"1234567891112131\n");
244 }
245
246 #[test]
247 fn lines_decoder_errors_on_overlong_line_without_delimiter() {
248 let mut codec = LinesCodec::new_with_max_length(4);
249 let mut buf = BytesMut::from(&b"aaaaa"[..]);
250
251 let err = codec.decode(&mut buf).unwrap_err();
252 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
253 }
254
255 #[test]
256 fn lines_decoder_resumes_from_previous_search() {
257 let mut codec = LinesCodec::default();
258 let mut buf = BytesMut::from(&b"partial"[..]);
259
260 assert!(codec.decode(&mut buf).unwrap().is_none());
261
262 buf.put_slice(b" line\n");
263 assert_eq!("partial line", codec.decode(&mut buf).unwrap().unwrap());
264 assert!(codec.decode(&mut buf).unwrap().is_none());
265 }
266
267 #[test]
268 fn lines_decoder_resumes_across_multiple_partial_chunks() {
269 let mut codec = LinesCodec::default();
270 let mut buf = BytesMut::new();
271
272 buf.put_slice(b"partial");
273 assert!(codec.decode(&mut buf).unwrap().is_none());
274
275 buf.put_slice(b" line");
276 assert!(codec.decode(&mut buf).unwrap().is_none());
277
278 buf.put_slice(b" across chunks");
279 assert!(codec.decode(&mut buf).unwrap().is_none());
280
281 buf.put_slice(b"\n");
282 assert_eq!(
283 "partial line across chunks",
284 codec.decode(&mut buf).unwrap().unwrap()
285 );
286 }
287
288 #[test]
289 fn lines_decoder_resumes_with_max_length() {
290 let mut codec = LinesCodec::new_with_max_length(18);
291 let mut buf = BytesMut::new();
292
293 buf.put_slice(b"partial");
294 assert!(codec.decode(&mut buf).unwrap().is_none());
295
296 buf.put_slice(b" line");
297 assert!(codec.decode(&mut buf).unwrap().is_none());
298
299 buf.put_slice(b" ok\n");
300 assert_eq!("partial line ok", codec.decode(&mut buf).unwrap().unwrap());
301 }
302
303 #[test]
304 fn lines_decoder_errors_on_overlong_partial_line() {
305 let mut codec = LinesCodec::new_with_max_length(4);
306 let mut buf = BytesMut::from(&b"aa"[..]);
307
308 assert!(codec.decode(&mut buf).unwrap().is_none());
309
310 buf.put_slice(b"aaa");
311 let err = codec.decode(&mut buf).unwrap_err();
312 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
313 }
314
315 #[test]
316 fn lines_decoder_resets_search_after_decode_eof() {
317 let mut codec = LinesCodec::default();
318 let mut buf = BytesMut::from(&b"partial"[..]);
319
320 assert!(codec.decode(&mut buf).unwrap().is_none());
321 assert_eq!("partial", codec.decode_eof(&mut buf).unwrap().unwrap());
322
323 buf.put_slice(b"next\n");
324 assert_eq!("next", codec.decode(&mut buf).unwrap().unwrap());
325 }
326}