1use half::f16;
2use std::io::{Result, Seek, Write};
3
4use crate::Endian;
5
6pub trait BinaryWrite {
7 fn write_bool(&mut self, value: bool) -> Result<()>;
9 fn write_char(&mut self, value: char) -> Result<()>;
11
12 fn write_u8(&mut self, value: u8) -> Result<()>;
14 fn write_u16(&mut self, value: u16) -> Result<()>;
16 fn write_u32(&mut self, value: u32) -> Result<()>;
18 fn write_u64(&mut self, value: u64) -> Result<()>;
20
21 fn write_i8(&mut self, value: i8) -> Result<()>;
23 fn write_i16(&mut self, value: i16) -> Result<()>;
25 fn write_i32(&mut self, value: i32) -> Result<()>;
27 fn write_i64(&mut self, value: i64) -> Result<()>;
29
30 fn write_f16(&mut self, value: f32) -> Result<()>;
32 fn write_f32(&mut self, value: f32) -> Result<()>;
34 fn write_f64(&mut self, value: f64) -> Result<()>;
36
37 fn write_cstr(&mut self, value: &str) -> Result<()>;
39 fn write_str(&mut self, value: &str, write_len: Option<bool>) -> Result<()>;
41 fn write_bytes(&mut self, value: &[u8], write_len: Option<bool>) -> Result<()>;
43
44 fn write_bool_array(&mut self, value: Vec<bool>, write_len: Option<bool>) -> Result<()>;
46 fn write_char_array(&mut self, value: Vec<char>, write_len: Option<bool>) -> Result<()>;
48 fn write_u8_array(&mut self, value: Vec<u8>, write_len: Option<bool>) -> Result<()>;
50 fn write_u16_array(&mut self, value: Vec<u16>, write_len: Option<bool>) -> Result<()>;
52 fn write_u32_array(&mut self, value: Vec<u32>, write_len: Option<bool>) -> Result<()>;
54 fn write_u64_array(&mut self, value: Vec<u64>, write_len: Option<bool>) -> Result<()>;
56 fn write_i8_array(&mut self, value: Vec<i8>, write_len: Option<bool>) -> Result<()>;
58 fn write_i16_array(&mut self, value: Vec<i16>, write_len: Option<bool>) -> Result<()>;
60 fn write_i32_array(&mut self, value: Vec<i32>, write_len: Option<bool>) -> Result<()>;
62 fn write_i64_array(&mut self, value: Vec<i64>, write_len: Option<bool>) -> Result<()>;
64 fn write_f16_array(&mut self, value: Vec<f32>, write_len: Option<bool>) -> Result<()>;
66 fn write_f32_array(&mut self, value: Vec<f32>, write_len: Option<bool>) -> Result<()>;
68 fn write_f64_array(&mut self, value: Vec<f64>, write_len: Option<bool>) -> Result<()>;
70 fn write_cstr_array(&mut self, value: Vec<&str>, write_len: Option<bool>) -> Result<()>;
72 fn write_str_array(&mut self, value: Vec<&str>, write_len: Option<bool>) -> Result<()>;
74 fn write_bytes_array(&mut self, value: Vec<&[u8]>, write_len: Option<bool>) -> Result<()>;
76}
77
78pub trait BinaryWriteAlign: BinaryWrite + Seek {
79 fn align(&mut self, alignment: usize) -> Result<()>;
81 fn align4(&mut self) -> Result<()> {
82 self.align(4)
83 }
84 fn align8(&mut self) -> Result<()> {
85 self.align(8)
86 }
87 fn align16(&mut self) -> Result<()> {
88 self.align(16)
89 }
90}
91
92macro_rules! build_write_array_fn {
93 ($name:ident, $func:ident, $type:ty) => {
94 fn $name(&mut self, value: Vec<$type>, write_len: Option<bool>) -> Result<()> {
95 if write_len.is_none() || write_len.unwrap() {
96 self.write_u32(value.len() as u32)?;
97 }
98 value.iter().for_each(|v| {
99 self.$func(*v).unwrap();
100 });
101 Ok(())
102 }
103 };
104}
105
106macro_rules! build_write_array_fn_arg {
107 ($name:ident, $func:ident, $type:ty) => {
108 fn $name(&mut self, value: Vec<$type>, write_len: Option<bool>) -> Result<()> {
109 if write_len.is_none() || write_len.unwrap() {
110 self.write_u32(value.len() as u32)?;
111 }
112 value.iter().for_each(|v| {
113 self.$func(v, Some(true)).unwrap();
114 });
115 Ok(())
116 }
117 };
118}
119
120macro_rules! write_fn_generic {
121 () => {
122 fn write_bool(&mut self, value: bool) -> Result<()> {
123 self.inner.write_all(&[value as u8])
124 }
125
126 fn write_char(&mut self, value: char) -> Result<()> {
127 self.inner.write_all(&[value as u8])
128 }
129
130 fn write_f16(&mut self, value: f32) -> Result<()> {
131 let value_f16 = f16::from_f32(value);
132 self.write_u16(value_f16.to_bits())
133 }
134
135 fn write_cstr(&mut self, value: &str) -> Result<()> {
136 self.inner.write_all(value.as_bytes())?;
137 self.inner.write_all(&[0u8])
138 }
139
140 fn write_str(&mut self, value: &str, write_len: Option<bool>) -> Result<()> {
141 if write_len.is_none() || write_len.unwrap() {
142 let str_len: u32 = value.len() as u32;
143 self.write_u32(str_len)?;
144 }
145 self.inner.write_all(value.as_bytes())
146 }
147
148 fn write_bytes(&mut self, value: &[u8], write_len: Option<bool>) -> Result<()> {
149 if write_len.is_none() || write_len.unwrap() {
150 let bytes_len: u32 = value.len() as u32;
151 self.write_u32(bytes_len)?;
152 }
153 self.inner.write_all(value)
154 }
155
156 build_write_array_fn!(write_bool_array, write_bool, bool);
157 build_write_array_fn!(write_char_array, write_char, char);
158 build_write_array_fn!(write_f16_array, write_f16, f32);
159 build_write_array_fn!(write_cstr_array, write_cstr, &str);
160 build_write_array_fn_arg!(write_str_array, write_str, &str);
161 build_write_array_fn_arg!(write_bytes_array, write_bytes, &[u8]);
162 };
163}
164
165macro_rules! build_write_fn_ve {
166 ($type:ty) => {
167 paste::item! {
168 fn [< write_ $type >] (&mut self, value: $type) -> Result<()> {
169 match self.endian {
170 Endian::Little => self.inner.write_all(&value.to_le_bytes()),
171 Endian::Big => self.inner.write_all(&value.to_be_bytes()),
172 }
173 }
174 }
175 paste::item! {
176 fn [< write_ $type _array >] (&mut self, value: Vec<$type>, write_len: Option<bool>) -> Result<()> {
177 if write_len.is_none() || write_len.unwrap() {
178 let array_len: u32 = value.len() as u32;
179 match self.endian {
180 Endian::Little => self.inner.write_all(&array_len.to_le_bytes())?,
181 Endian::Big => self.inner.write_all(&array_len.to_be_bytes())?,
182 };
183 }
184 match self.endian {
186 Endian::Little => {
187 value.iter().for_each(|v| {
188 self.inner.write_all(&v.to_le_bytes()).unwrap();
189 });
190 }
191 Endian::Big => {
192 value.iter().for_each(|v| {
193 self.inner.write_all(&v.to_be_bytes()).unwrap();
194 });
195 }
196 }
197 Ok(())
198 }
199 }
200 };
201}
202
203pub struct BinaryWriterVE<W> {
204 inner: W,
205 endian: Endian,
206}
207
208impl<W: Write> BinaryWriterVE<W> {
209 pub fn new(inner: W, endian: Endian) -> Self {
210 Self { inner, endian }
211 }
212}
213
214impl<W: Write> BinaryWrite for BinaryWriterVE<W> {
215 write_fn_generic!();
216 build_write_fn_ve!(u8);
217 build_write_fn_ve!(u16);
218 build_write_fn_ve!(u32);
219 build_write_fn_ve!(u64);
220
221 build_write_fn_ve!(i8);
222 build_write_fn_ve!(i16);
223 build_write_fn_ve!(i32);
224 build_write_fn_ve!(i64);
225 build_write_fn_ve!(f32);
226 build_write_fn_ve!(f64);
227}
228
229macro_rules! build_write_fn_be {
230 ($type:ty) => {
231 paste::item! {
232 fn [< write_ $type >] (&mut self, value: $type) -> Result<()> {
233 self.inner.write_all(&value.to_be_bytes())
234 }
235 }
236 paste::item! {
237 fn [< write_ $type _array >] (&mut self, value: Vec<$type>, write_len: Option<bool>) -> Result<()> {
238 if write_len.is_none() || write_len.unwrap() {
239 self.write_u32(value.len() as u32)?;
240 }
241 value.iter().for_each(|v| {
243 self.inner.write_all(&v.to_be_bytes()).unwrap();
244 });
245 Ok(())
246 }
247 }
248 };
249}
250pub struct BinaryWriterBE<W> {
251 inner: W,
252}
253
254impl<W: Write> BinaryWriterBE<W> {
255 pub fn new(inner: W) -> Self {
256 Self { inner }
257 }
258}
259
260impl<W: Write> BinaryWrite for BinaryWriterBE<W> {
261 write_fn_generic!();
262 build_write_fn_be!(u8);
263 build_write_fn_be!(u16);
264 build_write_fn_be!(u32);
265 build_write_fn_be!(u64);
266
267 build_write_fn_be!(i8);
268 build_write_fn_be!(i16);
269 build_write_fn_be!(i32);
270 build_write_fn_be!(i64);
271 build_write_fn_be!(f32);
272 build_write_fn_be!(f64);
273}
274
275macro_rules! build_write_fn_le {
276 ($type:ty) => {
277 paste::item! {
278 fn [< write_ $type >] (&mut self, value: $type) -> Result<()> {
279 self.inner.write_all(&value.to_le_bytes())
280 }
281 }
282 paste::item! {
283 fn [< write_ $type _array >] (&mut self, value: Vec<$type>, write_len: Option<bool>) -> Result<()> {
284 if write_len.is_none() || write_len.unwrap() {
285 self.write_u32(value.len() as u32)?;
286 }
287 value.iter().for_each(|v| {
289 self.inner.write_all(&v.to_le_bytes()).unwrap();
290 });
291 Ok(())
292 }
293 }
294 };
295}
296
297pub struct BinaryWriterLE<W> {
298 inner: W,
299}
300
301impl<W: Write> BinaryWriterLE<W> {
302 pub fn new(inner: W) -> Self {
303 Self { inner }
304 }
305}
306
307impl<W: Write> BinaryWrite for BinaryWriterLE<W> {
308 write_fn_generic!();
309 build_write_fn_le!(u8);
310 build_write_fn_le!(u16);
311 build_write_fn_le!(u32);
312 build_write_fn_le!(u64);
313
314 build_write_fn_le!(i8);
315 build_write_fn_le!(i16);
316 build_write_fn_le!(i32);
317 build_write_fn_le!(i64);
318 build_write_fn_le!(f32);
319 build_write_fn_le!(f64);
320}
321
322macro_rules! build_align_fn {
323 ($struct_:ident) => {
324 impl<R: Seek> $struct_<R> {
325 pub fn align(&mut self, alignment: usize) -> Result<()> {
326 let pos = self.inner.seek(std::io::SeekFrom::Current(0))?;
327 let rem = pos % alignment as u64;
328 if rem != 0 {
329 self.inner.seek(std::io::SeekFrom::Current(rem as i64))?;
330 }
331 Ok(())
332 }
333 }
334
335 impl<R: Seek> Seek for $struct_<R> {
336 fn seek(&mut self, pos: std::io::SeekFrom) -> Result<u64> {
337 self.inner.seek(pos)
338 }
339
340 fn stream_position(&mut self) -> Result<u64> {
341 self.inner.stream_position()
342 }
343 }
344 };
345}
346
347build_align_fn!(BinaryWriterLE);
348build_align_fn!(BinaryWriterBE);
349build_align_fn!(BinaryWriterVE);
350
351#[cfg(test)]
352mod tests {
353 use super::*;
354 fn write_unsigned(writer: &mut impl (BinaryWrite)) -> Result<()> {
355 writer.write_u8(0x1 as u8)?;
356 writer.write_u16(0x1234 as u16)?;
357 writer.write_u32(0x12345678 as u32)?;
358 writer.write_u64(0x1234567890123456 as u64)?;
359 Ok(())
360 }
361
362 fn write_signed(writer: &mut dyn BinaryWrite) -> Result<()> {
363 writer.write_i8(0x1 as i8)?;
364 writer.write_i16(-0x1234 as i16)?;
365 writer.write_i32(0x12345678 as i32)?;
366 writer.write_i64(-0x1234567890123456 as i64)?;
367 Ok(())
368 }
369
370 fn write_float(writer: &mut dyn BinaryWrite) -> Result<()> {
371 writer.write_f16(0.16)?;
372 writer.write_f32(-0.32)?;
373 writer.write_f64(0.64)?;
374 Ok(())
375 }
376
377 #[test]
378 pub fn test_binary_writer() {
379 let mut writer_vec = vec![];
380 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Little);
381 write_unsigned(&mut writer).unwrap();
382 assert_eq!(writer_vec, &b"\x014\x12xV4\x12V4\x12\x90xV4\x12"[..]);
383
384 let mut writer_vec = vec![];
385 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Little);
386 write_signed(&mut writer).unwrap();
387 assert_eq!(
388 writer_vec,
389 &b"\x01\xcc\xedxV4\x12\xaa\xcb\xedo\x87\xa9\xcb\xed"[..]
390 );
391
392 let mut writer_vec = vec![];
393 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Little);
394 write_float(&mut writer).unwrap();
395 assert_eq!(writer_vec, &b"\x1f1\n\xd7\xa3\xbe{\x14\xaeG\xe1z\xe4?"[..]);
396
397 let mut writer_vec = vec![];
398 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Big);
399 write_unsigned(&mut writer).unwrap();
400 assert_eq!(writer_vec, &b"\x01\x124\x124Vx\x124Vx\x90\x124V"[..]);
401
402 let mut writer_vec = vec![];
403 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Big);
404 write_signed(&mut writer).unwrap();
405 assert_eq!(
406 writer_vec,
407 &b"\x01\xed\xcc\x124Vx\xed\xcb\xa9\x87o\xed\xcb\xaa"[..]
408 );
409
410 let mut writer_vec = vec![];
411 let mut writer = BinaryWriterVE::new(&mut writer_vec, Endian::Big);
412 write_float(&mut writer).unwrap();
413 assert_eq!(writer_vec, &b"1\x1f\xbe\xa3\xd7\n?\xe4z\xe1G\xae\x14{"[..]);
414 }
415
416 #[test]
417 pub fn test_binary_writer_le() {
418 let mut writer_vec = vec![];
419 let mut writer = BinaryWriterLE::new(&mut writer_vec);
420 write_unsigned(&mut writer).unwrap();
421 assert_eq!(writer_vec, &b"\x014\x12xV4\x12V4\x12\x90xV4\x12"[..]);
422
423 let mut writer_vec = vec![];
424 let mut writer = BinaryWriterLE::new(&mut writer_vec);
425 write_signed(&mut writer).unwrap();
426 assert_eq!(
427 writer_vec,
428 &b"\x01\xcc\xedxV4\x12\xaa\xcb\xedo\x87\xa9\xcb\xed"[..]
429 );
430
431 let mut writer_vec = vec![];
432 let mut writer = BinaryWriterLE::new(&mut writer_vec);
433 write_float(&mut writer).unwrap();
434 assert_eq!(writer_vec, &b"\x1f1\n\xd7\xa3\xbe{\x14\xaeG\xe1z\xe4?"[..]);
435 }
436
437 #[test]
438 pub fn test_binary_writer_be() {
439 let mut writer_vec = vec![];
440 let mut writer = BinaryWriterBE::new(&mut writer_vec);
441 write_unsigned(&mut writer).unwrap();
442 assert_eq!(writer_vec, &b"\x01\x124\x124Vx\x124Vx\x90\x124V"[..]);
443
444 let mut writer_vec = vec![];
445 let mut writer = BinaryWriterBE::new(&mut writer_vec);
446 write_signed(&mut writer).unwrap();
447 assert_eq!(
448 writer_vec,
449 &b"\x01\xed\xcc\x124Vx\xed\xcb\xa9\x87o\xed\xcb\xaa"[..]
450 );
451
452 let mut writer_vec = vec![];
453 let mut writer = BinaryWriterBE::new(&mut writer_vec);
454 write_float(&mut writer).unwrap();
455 assert_eq!(writer_vec, &b"1\x1f\xbe\xa3\xd7\n?\xe4z\xe1G\xae\x14{"[..]);
456 }
457}