bytestream_rs/
writer.rs

1use byteorder::{BigEndian, LittleEndian, WriteBytesExt};
2use flate2::write::ZlibEncoder;
3use flate2::Compression;
4use std::io::Write;
5
6use crate::bytestream::{ByteStream, ByteStreamError};
7use crate::logiclong::LogicLong;
8
9impl ByteStream {
10    pub fn write_byte(&mut self, byte: u8) -> Result<(), ByteStreamError> {
11        self.cursor.write_u8(byte)?;
12        Ok(())
13    }
14
15    pub fn write_bool(&mut self, value: u8, bool: bool) -> Result<(), ByteStreamError> {
16        self.write_byte(if bool { value } else { 0 })?;
17        Ok(())
18    }
19
20    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ByteStreamError> {
21        self.cursor.write_all(bytes)?;
22        Ok(())
23    }
24
25    pub fn write_int8(&mut self, int8: i8) -> Result<(), ByteStreamError> {
26        self.cursor.write_i8(int8)?;
27        Ok(())
28    }
29
30    pub fn write_uint8(&mut self, uint8: u8) -> Result<(), ByteStreamError> {
31        self.cursor.write_u8(uint8)?;
32        Ok(())
33    }
34
35    pub fn write_int16(&mut self, int16: i16) -> Result<(), ByteStreamError> {
36        self.cursor.write_i16::<BigEndian>(int16)?;
37        Ok(())
38    }
39
40    pub fn write_uint16(&mut self, uint16: u16) -> Result<(), ByteStreamError> {
41        self.cursor.write_u16::<BigEndian>(uint16)?;
42        Ok(())
43    }
44
45    pub fn write_int24(&mut self, int24: i32) -> Result<(), ByteStreamError> {
46        self.cursor.write_i24::<BigEndian>(int24)?;
47        Ok(())
48    }
49
50    pub fn write_uint24(&mut self, uint24: u32) -> Result<(), ByteStreamError> {
51        self.cursor.write_u24::<BigEndian>(uint24)?;
52        Ok(())
53    }
54
55    pub fn write_int32(&mut self, int32: i32) -> Result<(), ByteStreamError> {
56        self.cursor.write_i32::<BigEndian>(int32)?;
57        Ok(())
58    }
59
60    pub fn write_int32_le(&mut self, int32: i32) -> Result<(), ByteStreamError> {
61        self.cursor.write_i32::<LittleEndian>(int32)?;
62        Ok(())
63    }
64
65    pub fn write_uint32(&mut self, uint32: u32) -> Result<(), ByteStreamError> {
66        self.cursor.write_u32::<BigEndian>(uint32)?;
67        Ok(())
68    }
69
70    pub fn write_int64(&mut self, int64: i64) -> Result<(), ByteStreamError> {
71        self.cursor.write_i64::<BigEndian>(int64)?;
72        Ok(())
73    }
74
75    pub fn write_uint64(&mut self, uint64: u64) -> Result<(), ByteStreamError> {
76        self.cursor.write_u64::<BigEndian>(uint64)?;
77        Ok(())
78    }
79
80    pub fn write_vint(&mut self, mut vint: i64) -> Result<(), ByteStreamError> {
81        let mut tmp = (vint >> 25) & 0x40;
82        let mut flipped = vint ^ (vint >> 31);
83
84        tmp |= vint & 0x3F;
85        vint >>= 6;
86
87        flipped >>= 6;
88        if flipped == 0 {
89            self.write_byte(tmp as u8)?;
90            return Ok(());
91        }
92
93        self.write_byte((tmp | 0x80) as u8)?;
94        loop {
95            flipped >>= 7;
96            let or_value = if flipped != 0 { 0x80 } else { 0 };
97            self.write_byte(((vint & 0x7F) | or_value) as u8)?;
98            vint >>= 7;
99            if flipped == 0 {
100                break;
101            }
102        }
103        Ok(())
104    }
105
106    pub fn write_long(&mut self, long: i64) -> Result<(), ByteStreamError> {
107        self.cursor.write_i64::<BigEndian>(long)?;
108        Ok(())
109    }
110
111    pub fn write_ulong(&mut self, ulong: u64) -> Result<(), ByteStreamError> {
112        self.cursor.write_u64::<BigEndian>(ulong)?;
113        Ok(())
114    }
115
116    pub fn write_longlong(&mut self, longlong: i64) -> Result<(), ByteStreamError> {
117        self.cursor.write_i64::<BigEndian>(longlong)?;
118        Ok(())
119    }
120
121    pub fn write_ulonglong(&mut self, ulonglong: u64) -> Result<(), ByteStreamError> {
122        self.cursor.write_u64::<BigEndian>(ulonglong)?;
123        Ok(())
124    }
125
126    pub fn write_string(&mut self, string: String) -> Result<(), ByteStreamError> {
127        // write length of string as i32, then string
128        let length = string.len() as i32;
129        if length == 0 || length == -1 {
130            self.cursor.write_i32::<BigEndian>(-1)?;
131            return Ok(());
132        }
133        self.cursor.write_i32::<BigEndian>(length)?;
134        self.cursor.write_all(string.as_bytes())?;
135        Ok(())
136    }
137
138    pub fn write_string_reference(&mut self, string: String) -> Result<(), ByteStreamError> {
139        // write length of string as i32, then string
140        let length = string.len() as i32;
141        if length == 0 || length == -1 {
142            self.cursor.write_i32::<BigEndian>(0)?; // difference here -
143            return Ok(());
144        }
145        self.cursor.write_i32::<BigEndian>(length)?;
146        self.cursor.write_all(string.as_bytes())?;
147        Ok(())
148    }
149
150    pub fn write_string_size(
151        &mut self,
152        size: usize,
153        string: String,
154    ) -> Result<(), ByteStreamError> {
155        // write size as i32, then string for size bytes
156        self.cursor.write_i32::<BigEndian>(size as i32)?;
157        // only write size bytes of string
158        self.cursor.write_all(&string.as_bytes()[..size])?;
159        Ok(())
160    }
161
162    pub fn write_string_size_reference(
163        &mut self,
164        size: usize,
165        string: String,
166    ) -> Result<(), ByteStreamError> {
167        // write size as i32, then string for size bytes
168        self.cursor.write_i32::<BigEndian>(size as i32)?;
169        // only write size bytes of string
170        self.cursor.write_all(&string.as_bytes()[..size])?;
171        Ok(())
172    }
173
174    pub fn write_compressed_string(&mut self, string: String) -> Result<(), ByteStreamError> {
175        // write length of compressed data as i32, then uncompressed data as i32 LE, then compressed data bytes
176        let uncompressed_size = string.len() as i32; // write LE
177
178        let mut compressor = ZlibEncoder::new(Vec::new(), Compression::default());
179        compressor.write_all(string.as_bytes())?;
180        let compressed_data = compressor.finish()?;
181        let compressed_size = compressed_data.len() as i32;
182
183        self.cursor.write_i32::<BigEndian>(compressed_size)?;
184        self.cursor.write_i32::<LittleEndian>(uncompressed_size)?;
185        self.cursor.write_all(&compressed_data)?;
186
187        Ok(())
188    }
189
190    pub fn write_logic_long(&mut self, logic_long: LogicLong) -> Result<(), ByteStreamError> {
191        self.cursor.write_u32::<BigEndian>(logic_long.low)?;
192        self.cursor.write_u32::<BigEndian>(logic_long.high)?;
193        Ok(())
194    }
195}