1use crate::{traits::BinaryFormat, TrackingWriter};
2use gaia_types::{GaiaError, QualifiedName, Result};
3use std::io::Write;
4
5pub struct BinaryWriter<W: Write, F: BinaryFormat> {
7 inner: TrackingWriter<W>,
8 diagnostics: Vec<GaiaError>,
9 _marker: std::marker::PhantomData<F>,
10}
11
12impl<W: Write, F: BinaryFormat> BinaryWriter<W, F> {
13 pub fn new(inner: W) -> Self {
15 Self { inner: TrackingWriter { inner, position: 0 }, diagnostics: Vec::new(), _marker: std::marker::PhantomData }
16 }
17
18 pub fn position(&self) -> u64 {
20 self.inner.position
21 }
22
23 pub fn add_error(&mut self, error: GaiaError) {
25 self.diagnostics.push(error);
26 }
27
28 pub fn take_errors(&mut self) -> Vec<GaiaError> {
30 std::mem::take(&mut self.diagnostics)
31 }
32
33 pub fn write_u8(&mut self, value: u8) -> Result<()> {
35 self.inner.write_all(&[value]).map_err(|_| GaiaError::truncated())
36 }
37
38 pub fn write_u16(&mut self, value: u16) -> Result<()> {
40 F::write_u16(&mut self.inner, value)
41 }
42
43 pub fn write_u32(&mut self, value: u32) -> Result<()> {
45 F::write_u32(&mut self.inner, value)
46 }
47
48 pub fn write_u64(&mut self, value: u64) -> Result<()> {
50 F::write_u64(&mut self.inner, value)
51 }
52
53 pub fn write_i16(&mut self, value: i16) -> Result<()> {
55 F::write_i16(&mut self.inner, value)
56 }
57
58 pub fn write_i32(&mut self, value: i32) -> Result<()> {
60 F::write_i32(&mut self.inner, value)
61 }
62
63 pub fn write_i64(&mut self, value: i64) -> Result<()> {
65 F::write_i64(&mut self.inner, value)
66 }
67
68 pub fn write_f32(&mut self, value: f32) -> Result<()> {
70 F::write_f32(&mut self.inner, value)
71 }
72
73 pub fn write_f64(&mut self, value: f64) -> Result<()> {
75 F::write_f64(&mut self.inner, value)
76 }
77
78 pub fn write_bytes(&mut self, buf: &[u8]) -> Result<()> {
80 self.inner.write_all(buf).map_err(|_| GaiaError::truncated())
81 }
82
83 pub fn write_all(&mut self, buf: &[u8]) -> Result<()> {
85 self.inner.write_all(buf).map_err(|_| GaiaError::truncated())
86 }
87
88 pub fn write_string(&mut self, s: &str) -> Result<()> {
90 let bytes = s.as_bytes();
91 self.write_u32(bytes.len() as u32)?;
92 self.write_bytes(bytes)
93 }
94
95 pub fn write_qualified_name(&mut self, qn: &QualifiedName) -> Result<()> {
97 self.write_u32(qn.namespace.len() as u32)?;
98 for part in &qn.namespace {
99 self.write_string(part)?;
100 }
101 self.write_string(&qn.name)
102 }
103
104 pub fn flush(&mut self) -> Result<()> {
106 self.inner.flush().map_err(|_| GaiaError::truncated())
107 }
108
109 pub fn into_inner(self) -> W {
111 self.inner.inner
112 }
113}
114
115impl<W: Write + std::io::Seek, F: BinaryFormat> std::io::Seek for BinaryWriter<W, F> {
116 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
117 self.inner.seek(pos)
118 }
119}
120
121impl<W: Write + std::fmt::Debug, F: BinaryFormat> std::fmt::Debug for BinaryWriter<W, F> {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 f.debug_struct("BinaryWriter").field("inner", &self.inner).field("position", &self.position()).finish()
124 }
125}