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 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 let length = string.len() as i32;
141 if length == 0 || length == -1 {
142 self.cursor.write_i32::<BigEndian>(0)?; 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 self.cursor.write_i32::<BigEndian>(size as i32)?;
157 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 self.cursor.write_i32::<BigEndian>(size as i32)?;
169 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 let uncompressed_size = string.len() as i32; 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}