forked from Quozul/PicoLimbo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary_writer.rs
More file actions
128 lines (105 loc) · 2.78 KB
/
binary_writer.rs
File metadata and controls
128 lines (105 loc) · 2.78 KB
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
127
128
use std::io::Write;
use std::num::TryFromIntError;
use thiserror::Error;
pub trait WriteBytes {
fn write(&self, writer: &mut BinaryWriter) -> Result<(), BinaryWriterError>;
}
#[derive(Debug, Default)]
pub struct BinaryWriter(pub(crate) Vec<u8>);
#[derive(Debug, Error)]
pub enum BinaryWriterError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
TryFromInt(#[from] TryFromIntError),
#[error("This operation is unsupported")]
UnsupportedOperation,
}
impl BinaryWriter {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn write<T: WriteBytes + ?Sized>(&mut self, value: &T) -> Result<(), BinaryWriterError> {
value.write(self)
}
pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<usize, BinaryWriterError> {
self.0.write(bytes).map_err(BinaryWriterError::from)
}
pub fn into_inner(self) -> Vec<u8> {
self.0
}
pub fn as_slice(&self) -> &[u8] {
&self.0
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) {
self.0.clear();
}
}
macro_rules! impl_write_int {
($($t:ty),*) => {
$(
impl WriteBytes for $t {
#[inline]
fn write(&self, writer: &mut BinaryWriter) -> Result<(), BinaryWriterError> {
writer.0.write_all(&self.to_be_bytes())?;
Ok(())
}
}
)*
}
}
impl_write_int!(
u8, i8, u16, i16, u32, i32, i64, u64, i128, u128, usize, f32, f64
);
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::{IntPrefixed, UShortPrefixed};
#[test]
fn test_unsigned_byte() {
// Given
let mut writer = BinaryWriter::default();
// When
writer.write(&0_u8).unwrap();
// Then
assert_eq!(vec![0], writer.into_inner());
}
#[test]
fn test_string() {
// Given
let mut writer = BinaryWriter::default();
let input = UShortPrefixed::string("hello world");
// When
writer.write(&input).unwrap();
// Then
assert_eq!(
vec![
0, 11, // String length
104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 // String content
],
writer.into_inner(),
);
}
#[test]
fn test_vec() {
// Given
let mut writer = BinaryWriter::default();
let input = vec![1_u8, 2, 3];
// When
writer.write(&IntPrefixed::new(input)).unwrap();
// Then
assert_eq!(
vec![
0, 0, 0, 3, // Vec length
1, 2, 3 // Data
],
writer.into_inner(),
);
}
}