scutiger_core/
pktline.rs

1#![allow(unknown_lints)]
2#![allow(bare_trait_objects)]
3#![allow(ellipsis_inclusive_range_patterns)]
4
5use super::errors::{Error, ErrorKind};
6use std::cmp;
7use std::io;
8
9/// The type of a packet received.
10#[derive(Eq, PartialEq, Debug, Copy, Clone)]
11pub enum PacketType {
12    /// A flush packet (0000).
13    Flush,
14    /// A delimiter packet (0001).
15    Delim,
16    /// A data packet.
17    ///
18    /// The contained value is the number of bytes of data read, not the packet value.
19    Data(usize),
20}
21
22/// A packet of data.
23#[derive(Eq, PartialEq, Debug, Clone)]
24pub struct Packet {
25    typ: PacketType,
26    data: Vec<u8>,
27}
28
29impl Packet {
30    pub fn new(t: PacketType, data: &[u8]) -> Self {
31        Packet {
32            typ: t,
33            data: data.to_vec(),
34        }
35    }
36
37    fn new_from_vec(t: PacketType, vec: Vec<u8>) -> Self {
38        Packet { typ: t, data: vec }
39    }
40
41    pub fn packet_type(&self) -> PacketType {
42        self.typ
43    }
44
45    pub fn data(&self) -> Option<&[u8]> {
46        match self.typ {
47            PacketType::Data(_) => Some(&self.data),
48            _ => None,
49        }
50    }
51}
52
53pub struct Reader<R: io::Read> {
54    rdr: R,
55    buf: [u8; 65536],
56    off: usize,
57    len: usize,
58}
59
60impl<R: io::Read> Reader<R> {
61    const MAX_PACKET_LEN: usize = 65516;
62
63    pub fn new(rdr: R) -> Self {
64        Reader {
65            rdr,
66            buf: [0u8; 65536],
67            off: 0,
68            len: 0,
69        }
70    }
71
72    fn read_one(rdr: &mut R, buf: &mut [u8]) -> Result<PacketType, Error> {
73        let mut hdr = [0u8; 4];
74        rdr.read_exact(&mut hdr)?;
75        let size = Self::parse_header(hdr)? as usize;
76        match size {
77            0 => Ok(PacketType::Flush),
78            1 => Ok(PacketType::Delim),
79            2 | 3 => Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
80            n if n > Self::MAX_PACKET_LEN + 4 => {
81                Err(Error::new_simple(ErrorKind::BadPktlineHeader))
82            }
83            _ => {
84                rdr.read_exact(&mut buf[0..(size - 4)])?;
85                Ok(PacketType::Data(size - 4))
86            }
87        }
88    }
89
90    pub fn read_packet(&mut self) -> Result<Packet, Error> {
91        let mut hdr = [0u8; 4];
92        self.rdr.read_exact(&mut hdr)?;
93        let size = Self::parse_header(hdr)? as usize;
94        match size {
95            0 => Ok(Packet::new(PacketType::Flush, b"")),
96            1 => Ok(Packet::new(PacketType::Delim, b"")),
97            2 | 3 => Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
98            _ => {
99                let mut v = vec![0u8; size - 4];
100                self.rdr.read_exact(&mut v)?;
101                Ok(Packet::new_from_vec(PacketType::Data(size - 4), v))
102            }
103        }
104    }
105
106    fn parse_header(buf: [u8; 4]) -> Result<u16, Error> {
107        let x: Result<Vec<u16>, Error> = buf
108            .iter()
109            .enumerate()
110            .map(|(i, x)| {
111                let v = match *x {
112                    b'0'...b':' => x - b'0',
113                    b'a'...b'g' => x - b'a' + 10,
114                    _ => return Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
115                };
116                Ok((v as u16) << ((3 - i) * 4))
117            })
118            .collect();
119        Ok(x?.into_iter().sum())
120    }
121
122    pub fn iter(&mut self) -> iter::ReaderIterator<'_, R> {
123        iter::ReaderIterator::new(self)
124    }
125}
126
127impl<R: io::Read> io::Read for Reader<R> {
128    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
129        let n = cmp::min(self.len - self.off, buf.len());
130        if n > 0 {
131            buf[0..n].copy_from_slice(&self.buf[self.off..self.off + n]);
132            if n == self.len - self.off {
133                self.off = 0;
134                self.len = 0;
135            } else {
136                self.off += n;
137            }
138            return Ok(n);
139        }
140        loop {
141            let (r, copy) = if buf.len() >= Self::MAX_PACKET_LEN {
142                (Self::read_one(&mut self.rdr, buf), false)
143            } else {
144                (Self::read_one(&mut self.rdr, &mut self.buf), true)
145            };
146            let n = match (r, copy) {
147                (Ok(PacketType::Delim), _) => return Ok(0),
148                (Ok(PacketType::Flush), _) => return Ok(0),
149                (Ok(PacketType::Data(0)), false) => n,
150                (Ok(PacketType::Data(n)), false) => return Ok(n),
151                (Ok(PacketType::Data(n)), true) => n,
152                (Err(e), _) => return Err(e.into()),
153            };
154            if n > 0 {
155                let c = cmp::min(n, buf.len());
156                buf[0..c].copy_from_slice(&self.buf[0..c]);
157                self.len = n;
158                self.off = c;
159                return Ok(c);
160            }
161        }
162    }
163}
164
165pub struct Writer<W: io::Write> {
166    writer: W,
167}
168
169impl<W: io::Write> Writer<W> {
170    const MAX_PACKET_LEN: usize = 65516;
171
172    pub fn new(writer: W) -> Self {
173        Writer { writer }
174    }
175
176    fn write_one(writer: &mut W, buf: &[u8]) -> Result<usize, Error> {
177        let header = format!("{:04x}", buf.len() + 4);
178        writer.write_all(header.as_bytes())?;
179        writer.write_all(buf)?;
180        Ok(buf.len())
181    }
182
183    pub fn write_packet(&mut self, pkt: &Packet) -> Result<usize, Error> {
184        match pkt.packet_type() {
185            PacketType::Flush => {
186                self.writer.write_all(b"0000")?;
187                self.writer.flush()?;
188                Ok(4)
189            }
190            PacketType::Delim => {
191                self.writer.write_all(b"0001")?;
192                Ok(4)
193            }
194            PacketType::Data(_) => Self::write_one(
195                &mut self.writer,
196                pkt.data()
197                    .ok_or_else(|| Error::new_simple(ErrorKind::InvalidPacket))?,
198            ),
199        }
200    }
201}
202
203impl<W: io::Write> io::Write for Writer<W> {
204    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
205        let mut total = 0;
206        for chunk in buf.chunks(Self::MAX_PACKET_LEN) {
207            total += match Self::write_one(&mut self.writer, chunk) {
208                Ok(sz) => sz,
209                Err(e) => return Err(e.into()),
210            }
211        }
212        Ok(total)
213    }
214
215    fn flush(&mut self) -> Result<(), io::Error> {
216        self.writer.flush()
217    }
218}
219
220mod iter {
221    use super::{Packet, Reader};
222    use crate::errors::Error;
223    use std::io;
224    use std::iter;
225
226    pub struct ReaderIterator<'a, R: io::Read> {
227        rdr: &'a mut Reader<R>,
228    }
229
230    impl<'a, R: io::Read> ReaderIterator<'a, R> {
231        pub fn new(rdr: &'a mut Reader<R>) -> Self {
232            ReaderIterator { rdr }
233        }
234    }
235
236    impl<'a, R: io::Read> iter::Iterator for ReaderIterator<'a, R> {
237        type Item = Result<Packet, Error>;
238
239        fn next(&mut self) -> Option<Result<Packet, Error>> {
240            match self.rdr.read_packet() {
241                Ok(x) => Some(Ok(x)),
242                Err(ref e) if e.io_kind() == io::ErrorKind::UnexpectedEof => None,
243                Err(e) => Some(Err(e)),
244            }
245        }
246    }
247}
248
249#[cfg(test)]
250mod tests {
251    use super::{Error, ErrorKind};
252    use super::{PacketType, Reader, Writer};
253    use std::io;
254    use std::io::Write;
255
256    fn reader_from_buf<'a>(buf: &'a [u8]) -> Reader<io::Cursor<&'a [u8]>> {
257        Reader::new(io::Cursor::new(buf))
258    }
259
260    fn writer() -> Writer<io::Cursor<Vec<u8>>> {
261        Writer::new(io::Cursor::new(Vec::new()))
262    }
263
264    fn check_packet(buf: &[u8], r: Result<(PacketType, Option<&[u8]>), Error>) {
265        let mut rdr = reader_from_buf(buf);
266        let mut v = vec![0u8; 65536];
267        let pt = Reader::read_one(&mut rdr.rdr, &mut v);
268        let data: Result<(PacketType, Option<&[u8]>), Error> = match pt {
269            Ok(PacketType::Data(x)) => {
270                v.truncate(x);
271                Ok((PacketType::Data(x), Some(&v)))
272            }
273            Ok(x) => Ok((x, None)),
274            Err(e) => Err(e),
275        };
276        assert_eq!(data, r);
277
278        let mut rdr = reader_from_buf(buf);
279        let pkt = rdr.read_packet();
280        let unwrapped = match &pkt {
281            &Ok(ref p) => Some(p.clone()),
282            &Err(_) => None,
283        };
284        assert_eq!(
285            pkt.map(|p| (p.packet_type().clone(), p.data().map(|x| x.to_vec()))),
286            r.map(|(pt, sl)| (pt.clone(), sl.map(|x| x.to_vec())))
287        );
288
289        if let Some(pkt) = unwrapped {
290            let mut wrtr = writer();
291            wrtr.write_packet(&pkt).unwrap();
292            assert_eq!(wrtr.writer.into_inner(), buf);
293        }
294    }
295
296    fn pattern_of_size(n: usize) -> Vec<u8> {
297        (0..n)
298            .map(|x| (x + (x >> 8) + (x >> 16) + (x >> 24)) as u8)
299            .collect()
300    }
301
302    #[test]
303    fn pktline_headers() {
304        assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0000"), Ok(0));
305        assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0001"), Ok(1));
306        assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0004"), Ok(4));
307        assert_eq!(
308            Reader::<io::Cursor<&[u8]>>::parse_header(*b"ffff"),
309            Ok(65535)
310        );
311        assert_eq!(
312            Reader::<io::Cursor<&[u8]>>::parse_header(*b"2204"),
313            Ok(8708)
314        );
315        assert_eq!(
316            Reader::<io::Cursor<&[u8]>>::parse_header(*b"cafe"),
317            Ok(51966)
318        );
319        assert_eq!(
320            Reader::<io::Cursor<&[u8]>>::parse_header(*b"cafE"),
321            Err(Error::new_simple(ErrorKind::BadPktlineHeader))
322        );
323        assert_eq!(
324            Reader::<io::Cursor<&[u8]>>::parse_header(*b"\xc2\xa9fe"),
325            Err(Error::new_simple(ErrorKind::BadPktlineHeader))
326        );
327    }
328
329    #[test]
330    fn parse_packet() {
331        check_packet(b"0000", Ok((PacketType::Flush, None)));
332        check_packet(b"0001", Ok((PacketType::Delim, None)));
333        check_packet(b"0004", Ok((PacketType::Data(0), Some(b""))));
334        check_packet(b"0005a", Ok((PacketType::Data(1), Some(b"a"))));
335        check_packet(
336            b"0046\xff\xfee3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
337            Ok((
338                PacketType::Data(66),
339                Some(b"\xff\xfee3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
340            )),
341        );
342    }
343
344    #[test]
345    fn write_data() {
346        let mut wrtr = writer();
347        wrtr.write(b"abc").unwrap();
348        wrtr.write(b"\xff\xfe\xc2\xa90123456").unwrap();
349        assert_eq!(
350            wrtr.writer.into_inner(),
351            b"0007abc000f\xff\xfe\xc2\xa90123456"
352        );
353    }
354
355    #[test]
356    fn write_data_large() {
357        let mut wrtr = writer();
358        let buf = pattern_of_size(65536);
359        let expected: [&[u8]; 4] = [b"fff0", &buf[0..65516], b"0018", &buf[65516..65536]];
360        let expected = expected.concat();
361        wrtr.write(&buf).unwrap();
362        wrtr.flush().unwrap();
363        assert_eq!(expected, wrtr.writer.into_inner());
364    }
365
366    #[test]
367    fn read_data_large() {
368        let buf = pattern_of_size(1048576);
369        for chunk_size in &[10, 17, 2204, 32768, 32771, 65516] {
370            let mut input: Vec<u8> = buf
371                .chunks(*chunk_size)
372                .flat_map(|x| {
373                    let mut vec = format!("{:04x}", x.len() + 4).as_bytes().to_vec();
374                    vec.extend(x);
375                    vec
376                })
377                .collect();
378            input.extend(b"0000");
379            let mut rdr = reader_from_buf(&input);
380            let mut cursor = io::Cursor::new(Vec::new());
381            io::copy(&mut rdr, &mut cursor).unwrap();
382            let actual = cursor.into_inner();
383            assert_eq!(buf, actual);
384        }
385    }
386}