1#![doc = include_str!("../README.md")]
2
3use std::error::Error;
4use std::fmt;
5use std::io::{self, Read, Write};
6use memchr::{memchr2, memchr2_iter};
7
8#[cfg(feature = "async-codec")]
9pub mod async_codec;
10#[cfg(feature = "tokio-codec")]
11pub mod tokio_codec;
12
13pub const END: u8 = 0xC0;
15pub const ESC: u8 = 0xDB;
17pub const ESC_END: u8 = 0xDC;
19pub const ESC_ESC: u8 = 0xDD;
21
22pub type Result<T> = std::result::Result<T, SlipError>;
24
25#[derive(Debug, Default, Clone, PartialEq, Eq)]
28pub struct FrameRemainder {
29 pub decoded: Vec<u8>,
31 pub escape_pending: bool,
33}
34
35impl FrameRemainder {
36 pub fn len(&self) -> usize {
38 self.decoded.len()
39 }
40
41 pub fn is_empty(&self) -> bool {
43 self.decoded.is_empty() && !self.escape_pending
44 }
45}
46
47#[derive(Debug)]
49#[non_exhaustive]
50pub enum SlipError {
51 Io(io::Error),
53 UnexpectedEndOfFrame,
55 IncompleteEscape,
57 InvalidEscape(u8),
59 MissingFrame,
61 MultipleFrames(usize),
63}
64
65impl fmt::Display for SlipError {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 match self {
68 SlipError::Io(err) => write!(f, "I/O error: {err}"),
69 SlipError::UnexpectedEndOfFrame => write!(f, "encountered unexpected end of frame"),
70 SlipError::IncompleteEscape => write!(f, "encountered incomplete escape sequence"),
71 SlipError::InvalidEscape(code) => {
72 write!(f, "encountered invalid escape sequence 0x{code:02X}")
73 }
74 SlipError::MissingFrame => write!(f, "no complete SLIP frame found in input"),
75 SlipError::MultipleFrames(count) => {
76 write!(f, "expected a single frame but found {count}")
77 }
78 }
79 }
80}
81
82impl Error for SlipError {
83 fn source(&self) -> Option<&(dyn Error + 'static)> {
84 match self {
85 SlipError::Io(err) => Some(err),
86 _ => None,
87 }
88 }
89}
90
91impl From<io::Error> for SlipError {
92 fn from(value: io::Error) -> Self {
93 SlipError::Io(value)
94 }
95}
96
97pub fn encode_frame(data: &[u8]) -> Vec<u8> {
102 let mut out = Vec::with_capacity(encoded_len_bytes(data));
104 let mut start = 0usize;
105 for pos in memchr2_iter(END, ESC, data) {
106 if pos > start {
107 out.extend_from_slice(&data[start..pos]);
108 }
109 match data[pos] {
110 END => out.extend_from_slice(&[ESC, ESC_END]),
111 ESC => out.extend_from_slice(&[ESC, ESC_ESC]),
112 _ => unreachable!(),
113 }
114 start = pos + 1;
115 }
116 if start < data.len() {
117 out.extend_from_slice(&data[start..]);
118 }
119 out.push(END);
120 out
121}
122
123pub fn encode_iter<I>(input: I) -> Vec<u8>
127where
128 I: IntoIterator<Item = u8>,
129{
130 let mut out = Vec::new();
131 encode_into_writer(input, &mut out).expect("writing to Vec<u8> cannot fail");
132 out
133}
134
135pub fn encode_into_writer<I, W>(input: I, writer: &mut W) -> Result<()>
140where
141 I: IntoIterator<Item = u8>,
142 W: Write,
143{
144 for byte in input {
145 match byte {
146 END => writer.write_all(&[ESC, ESC_END])?,
147 ESC => writer.write_all(&[ESC, ESC_ESC])?,
148 value => writer.write_all(&[value])?,
149 }
150 }
151 writer.write_all(&[END])?;
152 Ok(())
153}
154
155pub fn decode_frames(bytes: &[u8]) -> Result<Vec<Vec<u8>>> {
161 let (frames, remainder) = decode_frames_with_remainder(bytes)?;
162 if remainder.escape_pending {
163 return Err(SlipError::IncompleteEscape);
164 }
165 if !remainder.decoded.is_empty() {
166 return Err(SlipError::UnexpectedEndOfFrame);
167 }
168 Ok(frames)
169}
170
171pub fn decode_frames_iter<I>(input: I) -> Result<Vec<Vec<u8>>>
173where
174 I: IntoIterator<Item = u8>,
175{
176 let (frames, remainder) = decode_frames_iter_with_remainder(input)?;
177 if remainder.escape_pending {
178 return Err(SlipError::IncompleteEscape);
179 }
180 if !remainder.decoded.is_empty() {
181 return Err(SlipError::UnexpectedEndOfFrame);
182 }
183 Ok(frames)
184}
185
186pub fn decode_frames_with_remainder(bytes: &[u8]) -> Result<(Vec<Vec<u8>>, FrameRemainder)> {
199 let mut frames: Vec<Vec<u8>> = Vec::new();
200 let mut buffer: Vec<u8> = Vec::new();
201 let mut i = 0usize;
202 let mut escape_pending = false;
203
204 while i < bytes.len() {
205 if escape_pending {
206 let code = bytes[i];
207 match code {
208 ESC_END => buffer.push(END),
209 ESC_ESC => buffer.push(ESC),
210 invalid => return Err(SlipError::InvalidEscape(invalid)),
211 }
212 escape_pending = false;
213 i += 1;
214 continue;
215 }
216
217 match memchr2(END, ESC, &bytes[i..]) {
218 Some(rel) => {
219 let pos = i + rel;
220 if pos > i {
221 buffer.extend_from_slice(&bytes[i..pos]);
222 }
223 match bytes[pos] {
224 END => {
225 frames.push(std::mem::take(&mut buffer));
226 }
227 ESC => {
228 escape_pending = true;
229 }
230 _ => unreachable!(),
231 }
232 i = pos + 1;
233 }
234 None => {
235 buffer.extend_from_slice(&bytes[i..]);
237 i = bytes.len();
238 }
239 }
240 }
241
242 Ok((
243 frames,
244 FrameRemainder {
245 decoded: buffer,
246 escape_pending,
247 },
248 ))
249}
250
251pub fn decode_frames_iter_with_remainder<I>(input: I) -> Result<(Vec<Vec<u8>>, FrameRemainder)>
253where
254 I: IntoIterator<Item = u8>,
255{
256 let mut frames = Vec::new();
257 let mut buffer = Vec::new();
258 let mut state = DecoderState::default();
259
260 for byte in input {
261 let completed = process_byte(&mut state, byte, |value| buffer.push(value))?;
262 if completed {
263 frames.push(std::mem::take(&mut buffer));
264 }
265 }
266
267 Ok((
268 frames,
269 FrameRemainder {
270 decoded: buffer,
271 escape_pending: state.last_was_esc,
272 },
273 ))
274}
275
276pub fn encoded_len<I>(input: I) -> usize
284where
285 I: IntoIterator<Item = u8>,
286{
287 let mut len = 1; for byte in input {
289 len += match byte {
290 END | ESC => 2,
291 _ => 1,
292 };
293 }
294 len
295}
296
297fn encoded_len_bytes(bytes: &[u8]) -> usize {
299 let mut count = 0usize;
301 for _ in memchr2_iter(END, ESC, bytes) {
302 count += 1;
303 }
304 bytes.len() + count + 1
305}
306
307pub fn decoded_lengths(bytes: &[u8]) -> Result<Vec<usize>> {
316 let mut lengths: Vec<usize> = Vec::new();
317 let mut current = 0usize;
318 let mut i = 0usize;
319 let mut escape_pending = false;
320
321 while i < bytes.len() {
322 if escape_pending {
323 let code = bytes[i];
324 match code {
325 ESC_END | ESC_ESC => {
326 current += 1;
327 }
328 invalid => return Err(SlipError::InvalidEscape(invalid)),
329 }
330 escape_pending = false;
331 i += 1;
332 continue;
333 }
334
335 match memchr2(END, ESC, &bytes[i..]) {
336 Some(rel) => {
337 let pos = i + rel;
338 current += pos - i;
340 match bytes[pos] {
341 END => {
342 lengths.push(current);
343 current = 0;
344 }
345 ESC => {
346 escape_pending = true;
347 }
348 _ => unreachable!(),
349 }
350 i = pos + 1;
351 }
352 None => {
353 current += bytes.len() - i;
355 i = bytes.len();
356 }
357 }
358 }
359
360 if escape_pending {
361 return Err(SlipError::IncompleteEscape);
362 }
363 if current != 0 {
364 return Err(SlipError::UnexpectedEndOfFrame);
365 }
366 Ok(lengths)
367}
368
369pub fn decoded_lengths_iter<I>(input: I) -> Result<Vec<usize>>
371where
372 I: IntoIterator<Item = u8>,
373{
374 let mut lengths = Vec::new();
375 let mut current = 0usize;
376 let mut state = DecoderState::default();
377
378 for byte in input {
379 let completed = process_byte(&mut state, byte, |_| current += 1)?;
380 if completed {
381 lengths.push(current);
382 current = 0;
383 }
384 }
385
386 if state.last_was_esc {
387 return Err(SlipError::IncompleteEscape);
388 }
389
390 if current != 0 {
391 return Err(SlipError::UnexpectedEndOfFrame);
392 }
393
394 Ok(lengths)
395}
396
397pub fn decode_frame(bytes: &[u8]) -> Result<Vec<u8>> {
404 let mut frames = decode_frames(bytes)?;
405 match frames.len() {
406 0 => Err(SlipError::MissingFrame),
407 1 => Ok(frames.remove(0)),
408 count => Err(SlipError::MultipleFrames(count)),
409 }
410}
411
412pub struct SlipWriter<W> {
417 inner: W,
418}
419
420impl<W> SlipWriter<W> {
421 pub fn new(inner: W) -> Self {
423 Self { inner }
424 }
425
426 pub fn get_ref(&self) -> &W {
428 &self.inner
429 }
430
431 pub fn get_mut(&mut self) -> &mut W {
433 &mut self.inner
434 }
435
436 pub fn into_inner(self) -> W {
438 self.inner
439 }
440}
441
442impl<W: Write> SlipWriter<W> {
443 pub fn write_frame(&mut self, payload: &[u8]) -> Result<()> {
445 let frame = encode_frame(payload);
447 self.inner.write_all(&frame).map_err(SlipError::from)
448 }
449
450 pub fn write_frame_iter<I>(&mut self, payload: I) -> Result<()>
452 where
453 I: IntoIterator<Item = u8>,
454 {
455 encode_into_writer(payload, &mut self.inner)
456 }
457
458 pub fn flush(&mut self) -> Result<()> {
460 self.inner.flush().map_err(SlipError::from)
461 }
462}
463
464pub struct SlipReader<R> {
470 inner: R,
471 state: DecoderState,
472 pending: Vec<u8>,
473}
474
475impl<R> SlipReader<R> {
476 pub fn new(inner: R) -> Self {
478 Self {
479 inner,
480 state: DecoderState::default(),
481 pending: Vec::new(),
482 }
483 }
484
485 pub fn get_ref(&self) -> &R {
487 &self.inner
488 }
489
490 pub fn get_mut(&mut self) -> &mut R {
492 &mut self.inner
493 }
494
495 pub fn into_inner(self) -> R {
497 self.inner
498 }
499
500 pub fn into_inner_with_remainder(self) -> (R, FrameRemainder) {
502 (
503 self.inner,
504 FrameRemainder {
505 decoded: self.pending,
506 escape_pending: self.state.last_was_esc,
507 },
508 )
509 }
510}
511
512impl<R: Read> SlipReader<R> {
513 pub fn read_frame_into(&mut self, buffer: &mut Vec<u8>) -> Result<Option<usize>> {
518 buffer.clear();
519
520 loop {
521 let mut byte = [0u8; 1];
522 match self.inner.read(&mut byte) {
523 Ok(0) => {
524 if self.state.last_was_esc {
525 return Err(SlipError::IncompleteEscape);
526 }
527 if !self.pending.is_empty() {
528 return Err(SlipError::UnexpectedEndOfFrame);
529 }
530 return Ok(None);
531 }
532 Ok(_) => {
533 let completed =
534 process_byte(&mut self.state, byte[0], |value| self.pending.push(value))?;
535 if completed {
536 buffer.extend_from_slice(&self.pending);
537 let len = buffer.len();
538 self.pending.clear();
539 return Ok(Some(len));
540 }
541 }
542 Err(err) => return Err(SlipError::Io(err)),
543 }
544 }
545 }
546
547 pub fn read_frame(&mut self) -> Result<Option<Vec<u8>>> {
549 let mut frame = Vec::new();
550 match self.read_frame_into(&mut frame)? {
551 Some(_) => Ok(Some(frame)),
552 None => Ok(None),
553 }
554 }
555
556 pub fn read_frame_length(&mut self) -> Result<Option<usize>> {
572 let mut length = 0usize;
573
574 loop {
575 let mut byte = [0u8; 1];
576 match self.inner.read(&mut byte) {
577 Ok(0) => {
578 if self.state.last_was_esc {
579 return Err(SlipError::IncompleteEscape);
580 }
581 if !self.pending.is_empty() {
582 return Err(SlipError::UnexpectedEndOfFrame);
583 }
584 return Ok(None);
585 }
586 Ok(_) => {
587 let completed = process_byte(&mut self.state, byte[0], |value| {
588 self.pending.push(value);
589 length += 1;
590 })?;
591
592 if completed {
593 self.pending.clear();
594 return Ok(Some(length));
595 }
596 }
597 Err(err) => return Err(SlipError::Io(err)),
598 }
599 }
600 }
601
602 pub fn take_remainder(&mut self) -> FrameRemainder {
624 let remainder = FrameRemainder {
625 decoded: std::mem::take(&mut self.pending),
626 escape_pending: self.state.last_was_esc,
627 };
628 self.state.last_was_esc = false;
629 remainder
630 }
631
632 pub fn has_remainder(&self) -> bool {
634 !self.pending.is_empty() || self.state.last_was_esc
635 }
636}
637
638#[derive(Default)]
639pub(crate) struct DecoderState {
640 pub(crate) last_was_esc: bool,
641}
642
643fn process_byte<F>(state: &mut DecoderState, byte: u8, mut on_byte: F) -> Result<bool>
644where
645 F: FnMut(u8),
646{
647 if state.last_was_esc {
648 state.last_was_esc = false;
649 match byte {
650 ESC_END => on_byte(END),
651 ESC_ESC => on_byte(ESC),
652 invalid => return Err(SlipError::InvalidEscape(invalid)),
653 }
654 return Ok(false);
655 }
656
657 match byte {
658 END => {
659 state.last_was_esc = false;
660 Ok(true)
661 }
662 ESC => {
663 state.last_was_esc = true;
664 Ok(false)
665 }
666 value => {
667 on_byte(value);
668 Ok(false)
669 }
670 }
671}
672
673#[cfg(test)]
674mod tests {
675 use super::*;
676 use std::io::Cursor;
677
678 #[test]
679 fn encode_simple() {
680 let encoded = encode_frame(b"abc");
681 assert_eq!(encoded, vec![b'a', b'b', b'c', END]);
682 }
683
684 #[test]
685 fn encode_escapes() {
686 let encoded = encode_frame(&[END, ESC, 0x01]);
687 assert_eq!(encoded, vec![ESC, ESC_END, ESC, ESC_ESC, 0x01, END]);
688 }
689
690 #[test]
691 fn decode_single_frame() {
692 let frame = encode_frame(b"payload");
693 let decoded = decode_frame(&frame).unwrap();
694 assert_eq!(decoded, b"payload");
695 }
696
697 #[test]
698 fn decode_multiple_frames() {
699 let encoded = [encode_frame(b"one"), encode_frame(&[END])].concat();
700 let frames = decode_frames(&encoded).unwrap();
701 assert_eq!(frames.len(), 2);
702 assert_eq!(frames[0], b"one");
703 assert_eq!(frames[1], vec![END]);
704 }
705
706 #[test]
707 fn reader_writer_roundtrip() {
708 let mut writer = SlipWriter::new(Vec::new());
709 writer.write_frame(b"first").unwrap();
710 writer.write_frame(&[END]).unwrap();
711 let encoded = writer.into_inner();
712
713 let mut reader = SlipReader::new(Cursor::new(encoded));
714 let mut frame = Vec::new();
715 assert_eq!(reader.read_frame_into(&mut frame).unwrap(), Some(5));
716 assert_eq!(frame, b"first");
717 assert_eq!(reader.read_frame_into(&mut frame).unwrap(), Some(1));
718 assert_eq!(frame, vec![END]);
719 assert!(reader.read_frame_into(&mut frame).unwrap().is_none());
720 }
721
722 #[test]
723 fn decode_invalid_escape() {
724 let err = decode_frames(&[ESC, 0x01, END]).unwrap_err();
725 assert!(matches!(err, SlipError::InvalidEscape(0x01)));
726 }
727
728 #[test]
729 fn reader_incomplete_escape() {
730 let data = vec![ESC];
731 let mut reader = SlipReader::new(Cursor::new(data));
732 let mut frame = Vec::new();
733 let err = reader.read_frame_into(&mut frame).unwrap_err();
734 assert!(matches!(err, SlipError::IncompleteEscape));
735 }
736
737 #[test]
738 fn decode_frames_remainder_incomplete() {
739 let (frames, remainder) = decode_frames_with_remainder(&[0x01, 0x02]).unwrap();
740 assert!(frames.is_empty());
741 assert_eq!(remainder.decoded, vec![0x01, 0x02]);
742 assert!(!remainder.escape_pending);
743 }
744
745 #[test]
746 fn decode_frames_remainder_escape_pending() {
747 let input = [b'X', ESC];
748 let (frames, remainder) = decode_frames_with_remainder(&input).unwrap();
749 assert!(frames.is_empty());
750 assert_eq!(remainder.decoded, vec![b'X']);
751 assert!(remainder.escape_pending);
752 }
753
754 #[test]
755 fn decoded_lengths_multiple_frames() {
756 let encoded = [
757 encode_frame(b"foo"),
758 encode_frame(&[]),
759 encode_frame(&[END]),
760 ]
761 .concat();
762 let lengths = decoded_lengths(&encoded).unwrap();
763 assert_eq!(lengths, vec![3, 0, 1]);
764 }
765
766 #[test]
767 fn decoded_lengths_incomplete_frame_error() {
768 let mut encoded = encode_frame(b"broken");
769 encoded.pop(); let err = decoded_lengths(&encoded).unwrap_err();
771 assert!(matches!(err, SlipError::UnexpectedEndOfFrame));
772 }
773
774 #[test]
775 fn encoded_len_counts_escapes() {
776 let len = encoded_len([END, ESC, 0x01]);
777 assert_eq!(len, 6);
778 }
779
780 #[test]
781 fn reader_take_remainder_after_eof() {
782 let mut encoded = encode_frame(b"chunk");
783 encoded.pop();
784 let mut reader = SlipReader::new(Cursor::new(encoded));
785 let mut frame = Vec::new();
786 let err = reader.read_frame_into(&mut frame).unwrap_err();
787 assert!(matches!(err, SlipError::UnexpectedEndOfFrame));
788 assert!(frame.is_empty());
789 assert!(reader.has_remainder());
790 let remainder = reader.take_remainder();
791 assert_eq!(remainder.decoded, b"chunk");
792 assert!(!remainder.escape_pending);
793 assert!(!reader.has_remainder());
794 }
795
796 #[test]
797 fn reader_frame_length_only() {
798 let encoded = [
799 encode_frame(b"first"),
800 encode_frame(&[END]),
801 encode_frame(b""),
802 ]
803 .concat();
804 let mut reader = SlipReader::new(Cursor::new(encoded));
805 assert_eq!(reader.read_frame_length().unwrap(), Some(5));
806 assert_eq!(reader.read_frame_length().unwrap(), Some(1));
807 assert_eq!(reader.read_frame_length().unwrap(), Some(0));
808 assert!(reader.read_frame_length().unwrap().is_none());
809 }
810
811 #[test]
812 fn reader_frame_length_incomplete() {
813 let mut encoded = encode_frame(b"oops");
814 encoded.pop();
815 let mut reader = SlipReader::new(Cursor::new(encoded));
816 let err = reader.read_frame_length().unwrap_err();
817 assert!(matches!(err, SlipError::UnexpectedEndOfFrame));
818 let remainder = reader.take_remainder();
819 assert_eq!(remainder.decoded, b"oops");
820 assert!(!remainder.escape_pending);
821 }
822}