1use std::io::{Read, Write};
2
3use byteorder::{ReadBytesExt, WriteBytesExt};
4use err_derive::Error;
5
6pub(crate) type ByteOrder = byteorder::BigEndian;
7
8mod de;
9mod se;
10
11pub use crate::de::{from_reader, from_slice, Deserializer};
12pub use crate::se::{to_bytes, to_writer, Serializer};
13
14pub type Result<T> = std::result::Result<T, Error>;
15
16pub(crate) mod data_ids {
17 pub const NULL_ID: u8 = 0;
18 pub const BOOL_ID: u8 = 1;
19 pub const I8_ID: u8 = 2;
20 pub const I16_ID: u8 = 3;
21 pub const I32_ID: u8 = 4;
22 pub const I64_ID: u8 = 5;
23 pub const U8_ID: u8 = 6;
24 pub const U16_ID: u8 = 7;
25 pub const U32_ID: u8 = 8;
26 pub const U64_ID: u8 = 9;
27 pub const F32_ID: u8 = 10;
28 pub const F64_ID: u8 = 11;
29 pub const CHAR_ID: u8 = 12;
30 pub const STR_ID: u8 = 13;
31 pub const BYTES_ID: u8 = 14;
32 pub const SEQ_ID: u8 = 15;
33 pub const TUPLE_ID: u8 = 16;
34 pub const UNIT_VARIANT_ID: u8 = 17;
35 pub const ENUM_VARIANT_ID: u8 = 18;
36 pub const TUPLE_STRUCT_ID: u8 = 19;
37 pub const MAP_ID: u8 = 20;
38}
39
40#[derive(Debug, Error)]
41pub enum Error {
42 #[error(display = "IO error: {}", _0)]
43 IoError(#[source] std::io::Error),
44 #[error(display = "From utf8 error: {}", _0)]
45 FromUtf8Error(#[source] std::string::FromUtf8Error),
46 #[error(display = "'{}' is not a valid compression format", _0)]
47 InvalidCompression(u8),
48 #[error(display = "{}", _0)]
49 Custom(String),
50 #[error(display = "Lengths are required for the sbif format")]
51 LengthRequired,
52 #[error(display = "Unexpected string")]
53 UnexpectedString,
54 #[error(
55 display = "Invalid access order. You cannot access 2 map keys or 2 map values in a row"
56 )]
57 InvalidMapAccess,
58 #[error(display = "Invalid sbif header: expected 'SBIF', found {}", _0)]
59 InvalidHeader(String),
60 #[error(display = "Invalid data id: expected {}, found {}", expected, found)]
61 InvalidDataId { expected: String, found: u8 },
62 #[error(
63 display = "Invalid sbif version: expected {}, found {}",
64 expected,
65 found
66 )]
67 InvalidVersion { expected: u8, found: u8 },
68 #[error(display = "{}: expected {}, actual {}", message, expected, actual)]
69 InvalidLength {
70 expected: usize,
71 actual: usize,
72 message: String,
73 },
74}
75
76impl serde::ser::Error for Error {
77 fn custom<T>(msg: T) -> Self
78 where
79 T: std::fmt::Display,
80 {
81 Self::Custom(msg.to_string())
82 }
83}
84
85impl serde::de::Error for Error {
86 fn custom<T>(msg: T) -> Self
87 where
88 T: std::fmt::Display,
89 {
90 Self::Custom(msg.to_string())
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub enum Compression {
97 None,
98 Deflate(u32),
99 GZip(u32),
100 ZLib(u32),
101}
102
103impl Default for Compression {
104 fn default() -> Self {
105 Self::GZip(6)
106 }
107}
108
109pub(crate) struct FileHeader {
110 pub(crate) compression: Compression,
111 pub(crate) version: u8,
112 pub(crate) header_name: String,
113}
114
115impl Default for FileHeader {
116 fn default() -> Self {
117 Self::new(Compression::default())
118 }
119}
120
121impl FileHeader {
122 pub fn new(compression: Compression) -> Self {
123 Self {
124 compression,
125 version: 1,
126 header_name: String::from("SBIF"),
127 }
128 }
129
130 pub fn to_writer<W: Write>(&self, writer: &mut W) -> Result<()> {
131 let name_bytes = self.header_name.as_bytes();
132 writer
133 .write_u16::<ByteOrder>(name_bytes.len() as u16)
134 .map_err(Error::IoError)?;
135 writer.write(name_bytes).map_err(Error::IoError)?;
136 writer.write_u8(self.version).map_err(Error::IoError)?;
137
138 match self.compression {
139 Compression::None => writer.write_u8(0).map_err(Error::IoError)?,
140 Compression::Deflate(v) => {
141 writer.write_u8(1).map_err(Error::IoError)?;
142 writer.write_u32::<ByteOrder>(v).map_err(Error::IoError)?;
143 }
144 Compression::GZip(v) => {
145 writer.write_u8(2).map_err(Error::IoError)?;
146 writer.write_u32::<ByteOrder>(v).map_err(Error::IoError)?;
147 }
148 Compression::ZLib(v) => {
149 writer.write_u8(3).map_err(Error::IoError)?;
150 writer.write_u32::<ByteOrder>(v).map_err(Error::IoError)?;
151 }
152 };
153
154 Ok(())
155 }
156
157 #[cfg(test)]
158 pub fn to_bytes(&self) -> Result<Vec<u8>> {
159 let mut buffer = Vec::new();
160 self.to_writer(&mut buffer)?;
161 Ok(buffer)
162 }
163
164 pub fn from_reader<R: Read>(reader: &mut R) -> Result<Self> {
165 let header_name = {
166 let name_length = reader.read_u16::<ByteOrder>().map_err(Error::IoError)? as usize;
167 let mut buffer = vec![0_u8; name_length];
168 reader.read_exact(&mut buffer).map_err(Error::IoError)?;
169 String::from_utf8(buffer).map_err(Error::FromUtf8Error)?
170 };
171
172 let version = reader.read_u8().map_err(Error::IoError)?;
173 let compression = match reader.read_u8().map_err(Error::IoError)? {
174 0 => Compression::None,
175 1 => Compression::Deflate(reader.read_u32::<ByteOrder>().map_err(Error::IoError)?),
176 2 => Compression::GZip(reader.read_u32::<ByteOrder>().map_err(Error::IoError)?),
177 3 => Compression::ZLib(reader.read_u32::<ByteOrder>().map_err(Error::IoError)?),
178 v => return Err(Error::InvalidCompression(v)),
179 };
180
181 Ok(Self {
182 compression,
183 version,
184 header_name,
185 })
186 }
187}