1use bytes::{Buf, BufMut};
10use snafu::{ResultExt, Snafu};
11use std::convert::TryInto;
12use std::io::Read;
13use std::io::Write;
14
15#[derive(Debug, Snafu)]
16pub enum Error {
17 ItemTooLong { source: std::num::TryFromIntError },
18 WriteError { source: std::io::Error },
19 ReadError { source: std::io::Error },
20}
21
22#[derive(PartialEq, Debug)]
23pub struct SLP(pub Vec<Vec<u8>>);
24
25impl SLP {
27 pub fn encode_write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
28 self.0.iter().try_for_each(|bytes| {
29 let byte_len: u16 = bytes.len().try_into().context(ItemTooLong)?;
30 let mut length_buf = [0u8; 2];
31 (&mut length_buf[..]).put_u16_le(byte_len);
32
33 writer.write(&length_buf).context(WriteError)?;
34 writer.write(&bytes).context(WriteError)?;
35
36 Ok::<(), Error>(())
37 })?;
38
39 Ok(())
40 }
41
42 pub fn decode_read<R: Read>(reader: &mut R) -> Result<Self, Error> {
43 let mut items = Vec::new();
44
45 let mut length_buf = [0u8; 2];
46
47 while let Ok(_) = reader.read_exact(&mut length_buf) {
48 let byte_len = (&length_buf[..]).get_u16_le();
49 let mut item = Vec::with_capacity(byte_len as usize);
50 item.resize(byte_len as usize, 0);
51 reader.read_exact(&mut item).context(ReadError)?;
52 items.push(item);
53 }
54 Ok(SLP(items))
55 }
56
57 pub fn into_inner(self) -> Vec<Vec<u8>> {
58 self.0
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use crate::*;
65 #[test]
66 fn encode_decode() {
67 let data = vec![vec![1u8, 2, 3], vec![4u8, 5, 6, 7]];
68 let slp = SLP(data);
69
70 let mut encode_writer = vec![];
71 slp.encode_write(&mut encode_writer).unwrap();
72
73 let decoded = SLP::decode_read(&mut encode_writer.as_slice()).unwrap();
74
75 assert_eq!(decoded, slp);
76 }
77}