1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::io::{Read, Write};
use crate::{error::{BinverseError, BinverseResult}, serialize::{Deserialize, Serialize, SizeBytes, SizedDeserialize, SizedSerialize}, varint};
/// A serializer used to write serialized data to the writer.
pub struct Serializer<W: Write> {
pub(crate) w: W,
}
impl<W: Write> Serializer<W> {
/// Creates a new serializer. The revision will be written to the data to
/// make it possible to parse the data in future revisions. If the revision
/// should not be written, use [`Serializer::new_no_revision`].
pub fn new(w: W, revision: u32) -> BinverseResult<Self> {
let mut s = Self { w };
revision.serialize(&mut s)?;
Ok(s)
}
/// Create a new Serializer, but without writing the revision into the stream.
pub fn new_no_revision(w: W) -> Self {
Self { w }
}
/// Write a raw byte buffer into the output. Should only be used when the
/// size will be known when deserializing, use the [SizedSerialize]/[SizedDeserialize]
/// implementations for `[u8]` or `Vec<u8>` otherwise.
pub fn write(&mut self, buf: &[u8]) -> BinverseResult<()> {
self.w.write_all(buf)?;
Ok(())
}
pub(crate) fn write_size(&mut self, sb: SizeBytes, size: usize) -> BinverseResult<()> {
use SizeBytes::*;
let max_size = match sb {
One => u8::MAX as usize,
Two => u16::MAX as usize,
Four => u32::MAX as usize,
Eight | Var => u64::MAX as usize,
};
if size > max_size {
return Err(BinverseError::SizeExceeded { limit: sb, found: size });
}
match sb {
SizeBytes::One => (size as u8).serialize(self),
SizeBytes::Two => (size as u16).serialize(self),
SizeBytes::Four => (size as u32).serialize(self),
SizeBytes::Eight => (size as u64).serialize(self),
SizeBytes::Var => varint::write(size as u64, &mut self.w)
}
}
/// Serialize a sized data structure. Use the `size_bytes` parameter to
/// control how many bytes are used to serialize the size of the data structure.
/// Note that any elements exceeding the size will not be serialized.
/// For example, a [Vec] with 258 elements will lose it's last 3 elements
/// when using [SizeBytes::One].
pub fn serialize_sized<T: SizedSerialize<W>>(&mut self, size_bytes: SizeBytes, t: &T) -> BinverseResult<()> {
let size = t.size();
self.write_size(size_bytes, size)?;
t.serialize_sized(self, size)
}
/// Returns the inner writer.
pub fn finish(self) -> W { self.w }
}
/// Reads previously serialized data from a reader. Note that all calls must be
/// the opposite from the calls used when serializing so the data matches.
pub struct Deserializer<R: Read> {
pub(crate) r: R,
revision: u32
}
impl<R: Read> Deserializer<R> {
/// Creates a new deserializer from an underlying reader. The revision
/// is read from the reader. If the revision should not be read, use
/// [`Deserializer::new_no_revision`].
pub fn new(r: R) -> BinverseResult<Self> {
let mut d = Self {
r,
revision: 0
};
d.revision = d.deserialize()?;
Ok(d)
}
/// Create a new Deserializer, but without reading the revision from the stream.
/// Instead, the revision has to be passed. Providing data created in a different
/// revision than specified can lead to invalid data or errors.
pub fn new_no_revision(r: R, revision: u32) -> Self {
Self { r, revision }
}
/// Reads raw bytes into a byte slice. Should only be used when
/// implementing new [Deserialize] implementations that can't make use of
/// existing implementations.
pub fn read(&mut self, buf: &mut [u8]) -> BinverseResult<()> {
self.r.read_exact(buf)?;
Ok(())
}
pub(crate) fn read_size(&mut self, sb: SizeBytes) -> BinverseResult<usize> {
Ok(match sb {
SizeBytes::One => self.deserialize::< u8>()? as usize,
SizeBytes::Two => self.deserialize::<u16>()? as usize,
SizeBytes::Four => self.deserialize::<u32>()? as usize,
SizeBytes::Eight => self.deserialize::<u64>()? as usize,
SizeBytes::Var => varint::read(&mut self.r)? as usize
})
}
/// Deserializes something. The type has to be known and has to match the
/// type that was serialized previously.
pub fn deserialize<T: Deserialize<R>>(&mut self) -> BinverseResult<T> { T::deserialize(self) }
/// Deserializes a data structure with a size. Type and size_bytes have to
/// match the serialized data structure.
pub fn deserialize_sized<T: SizedDeserialize<R>>(&mut self, size_bytes: SizeBytes) -> BinverseResult<T> {
let size = self.read_size(size_bytes)?;
T::deserialize_sized(self, size)
}
/// Get the revision of the data currently being deserialized. Used when
/// reading version-dependent data.
pub fn revision(&self) -> u32 { self.revision }
/// Returns the inner reader.
pub fn finish(self) -> R { self.r }
}