1use crate::error::Result;
18use crate::records::*;
19use std::io::Write;
20
21pub struct Encoder<W: Write> {
23 writer: W,
24}
25
26impl<W: Write> Encoder<W> {
27 pub fn new(writer: W) -> Self {
29 Self { writer }
30 }
31
32 pub fn encode(&mut self, record: &Record) -> Result<()> {
34 match record {
35 Record::SerializationHeader(rec) => {
36 self.write_u8(RecordType::SerializedStreamHeader as u8)?;
37 self.write_serialization_header(rec)?;
38 }
39 Record::BinaryLibrary(rec) => {
40 self.write_u8(RecordType::BinaryLibrary as u8)?;
41 self.write_binary_library(rec)?;
42 }
43 Record::ClassWithMembersAndTypes(rec) => {
44 self.write_u8(RecordType::ClassWithMembersAndTypes as u8)?;
45 self.write_class_with_members_and_types(rec)?;
46 }
47 Record::SystemClassWithMembersAndTypes(rec) => {
48 self.write_u8(RecordType::SystemClassWithMembersAndTypes as u8)?;
49 self.write_system_class_with_members_and_types(rec)?;
50 }
51 Record::SystemClassWithMembers(rec) => {
52 self.write_u8(RecordType::SystemClassWithMembers as u8)?;
53 self.write_system_class_with_members(rec)?;
54 }
55 Record::ClassWithMembers(rec) => {
56 self.write_u8(RecordType::ClassWithMembers as u8)?;
57 self.write_class_with_members(rec)?;
58 }
59 Record::ClassWithId(rec) => {
60 self.write_u8(RecordType::ClassWithId as u8)?;
61 self.write_class_with_id(rec)?;
62 }
63 Record::BinaryObjectString { object_id, value } => {
64 self.write_u8(RecordType::BinaryObjectString as u8)?;
65 self.write_i32(*object_id)?;
66 self.write_length_prefixed_string(value)?;
67 }
68 Record::BinaryArray(rec) => {
69 self.write_u8(RecordType::BinaryArray as u8)?;
70 self.write_binary_array(rec)?;
71 }
72 Record::ArraySingleObject(rec) => {
73 self.write_u8(RecordType::ArraySingleObject as u8)?;
74 self.write_i32(rec.object_id)?;
75 self.write_i32(rec.length)?;
76 for val in &rec.element_values {
77 self.write_object_value(val)?;
78 }
79 }
80 Record::ArraySinglePrimitive(rec) => {
81 self.write_u8(RecordType::ArraySinglePrimitive as u8)?;
82 self.write_i32(rec.object_id)?;
83 self.write_i32(rec.length)?;
84 self.write_u8(rec.primitive_type_enum as u8)?;
85 for val in &rec.element_values {
86 self.write_primitive_value(val)?;
87 }
88 }
89 Record::ArraySingleString(rec) => {
90 self.write_u8(RecordType::ArraySingleString as u8)?;
91 self.write_i32(rec.object_id)?;
92 self.write_i32(rec.length)?;
93 for val in &rec.element_values {
94 self.write_object_value(val)?;
95 }
96 }
97 Record::MemberPrimitiveTyped {
98 primitive_type_enum,
99 value,
100 } => {
101 self.write_u8(RecordType::MemberPrimitiveTyped as u8)?;
102 self.write_u8(*primitive_type_enum as u8)?;
103 self.write_primitive_value(value)?;
104 }
105 Record::MemberReference { id_ref } => {
106 self.write_u8(RecordType::MemberReference as u8)?;
107 self.write_i32(*id_ref)?;
108 }
109 Record::ObjectNull => {
110 self.write_u8(RecordType::ObjectNull as u8)?;
111 }
112 Record::ObjectNullMultiple(rec) => {
113 self.write_u8(RecordType::ObjectNullMultiple as u8)?;
114 self.write_i32(rec.null_count)?;
115 }
116 Record::ObjectNullMultiple256(rec) => {
117 self.write_u8(RecordType::ObjectNullMultiple256 as u8)?;
118 self.write_u8(rec.null_count)?;
119 }
120 Record::MessageEnd => {
121 self.write_u8(RecordType::MessageEnd as u8)?;
122 }
123 }
124 Ok(())
125 }
126
127 fn write_i32(&mut self, val: i32) -> Result<()> {
128 self.writer.write_all(&val.to_le_bytes())?;
129 Ok(())
130 }
131
132 fn write_u8(&mut self, val: u8) -> Result<()> {
133 self.writer.write_all(&[val])?;
134 Ok(())
135 }
136
137 fn write_serialization_header(&mut self, rec: &SerializationHeader) -> Result<()> {
138 self.write_i32(rec.root_id)?;
139 self.write_i32(rec.header_id)?;
140 self.write_i32(rec.major_version)?;
141 self.write_i32(rec.minor_version)?;
142 Ok(())
143 }
144
145 fn write_binary_library(&mut self, rec: &BinaryLibrary) -> Result<()> {
146 self.write_i32(rec.library_id)?;
147 self.write_length_prefixed_string(&rec.library_name)?;
148 Ok(())
149 }
150
151 fn write_length_prefixed_string(&mut self, s: &str) -> Result<()> {
152 let bytes = s.as_bytes();
153 self.write_variable_length_int(bytes.len() as i32)?;
154 self.writer.write_all(bytes)?;
155 Ok(())
156 }
157
158 fn write_variable_length_int(&mut self, mut value: i32) -> Result<()> {
159 loop {
160 let mut b = (value & 0x7F) as u8;
161 value >>= 7;
162 if value > 0 {
163 b |= 0x80;
164 self.write_u8(b)?;
165 } else {
166 self.write_u8(b)?;
167 break;
168 }
169 }
170 Ok(())
171 }
172
173 fn write_class_info(&mut self, info: &ClassInfo) -> Result<()> {
174 self.write_i32(info.object_id)?;
175 self.write_length_prefixed_string(&info.name)?;
176 self.write_i32(info.member_count)?;
177 for name in &info.member_names {
178 self.write_length_prefixed_string(name)?;
179 }
180 Ok(())
181 }
182
183 fn write_member_type_info(&mut self, info: &MemberTypeInfo) -> Result<()> {
184 for bt in &info.binary_type_enums {
185 self.write_u8(*bt as u8)?;
186 }
187 for info in &info.additional_infos {
188 match info {
189 AdditionalTypeInfo::Primitive(pt) => self.write_u8(*pt as u8)?,
190 AdditionalTypeInfo::SystemClass(s) => self.write_length_prefixed_string(s)?,
191 AdditionalTypeInfo::Class(c) => {
192 self.write_length_prefixed_string(&c.type_name)?;
193 self.write_i32(c.library_id)?;
194 }
195 AdditionalTypeInfo::None => {}
196 }
197 }
198 Ok(())
199 }
200
201 fn write_class_with_members_and_types(&mut self, rec: &ClassWithMembersAndTypes) -> Result<()> {
202 self.write_class_info(&rec.class_info)?;
203 self.write_member_type_info(&rec.member_type_info)?;
204 self.write_i32(rec.library_id)?;
205 for val in &rec.member_values {
206 self.write_object_value(val)?;
207 }
208 Ok(())
209 }
210
211 fn write_system_class_with_members_and_types(
212 &mut self,
213 rec: &SystemClassWithMembersAndTypes,
214 ) -> Result<()> {
215 self.write_class_info(&rec.class_info)?;
216 self.write_member_type_info(&rec.member_type_info)?;
217 for val in &rec.member_values {
218 self.write_object_value(val)?;
219 }
220 Ok(())
221 }
222
223 fn write_system_class_with_members(&mut self, rec: &SystemClassWithMembers) -> Result<()> {
224 self.write_class_info(&rec.class_info)?;
225 for val in &rec.member_values {
226 self.write_object_value(val)?;
227 }
228 Ok(())
229 }
230
231 fn write_class_with_members(&mut self, rec: &ClassWithMembers) -> Result<()> {
232 self.write_class_info(&rec.class_info)?;
233 self.write_i32(rec.library_id)?;
234 for val in &rec.member_values {
235 self.write_object_value(val)?;
236 }
237 Ok(())
238 }
239
240 fn write_class_with_id(&mut self, rec: &ClassWithId) -> Result<()> {
241 self.write_i32(rec.object_id)?;
242 self.write_i32(rec.metadata_id)?;
243 for val in &rec.member_values {
244 self.write_object_value(val)?;
245 }
246 Ok(())
247 }
248
249 fn write_binary_array(&mut self, rec: &BinaryArray) -> Result<()> {
250 self.write_i32(rec.object_id)?;
251 self.write_u8(rec.binary_array_type_enum)?;
252 self.write_i32(rec.rank)?;
253 for len in &rec.lengths {
254 self.write_i32(*len)?;
255 }
256 if let Some(bounds) = &rec.lower_bounds {
257 for bound in bounds {
258 self.write_i32(*bound)?;
259 }
260 }
261 self.write_u8(rec.type_enum as u8)?;
262 match &rec.additional_type_info {
263 AdditionalTypeInfo::Primitive(pt) => self.write_u8(*pt as u8)?,
264 AdditionalTypeInfo::SystemClass(s) => self.write_length_prefixed_string(s)?,
265 AdditionalTypeInfo::Class(c) => {
266 self.write_length_prefixed_string(&c.type_name)?;
267 self.write_i32(c.library_id)?;
268 }
269 AdditionalTypeInfo::None => {}
270 }
271 for val in &rec.element_values {
272 self.write_object_value(val)?;
273 }
274 Ok(())
275 }
276
277 fn write_primitive_value(&mut self, val: &PrimitiveValue) -> Result<()> {
278 match val {
279 PrimitiveValue::Boolean(b) => self.write_u8(if *b { 1 } else { 0 })?,
280 PrimitiveValue::Byte(b) => self.write_u8(*b)?,
281 PrimitiveValue::Char(c) => self.write_u8(*c as u8)?,
282 PrimitiveValue::Int16(v) => self.writer.write_all(&v.to_le_bytes())?,
283 PrimitiveValue::Int32(v) => self.write_i32(*v)?,
284 PrimitiveValue::Int64(v) => self.writer.write_all(&v.to_le_bytes())?,
285 PrimitiveValue::SByte(v) => self.write_u8(*v as u8)?,
286 PrimitiveValue::Single(v) => self.writer.write_all(&v.to_le_bytes())?,
287 PrimitiveValue::Double(v) => self.writer.write_all(&v.to_le_bytes())?,
288 PrimitiveValue::TimeSpan(v) => self.writer.write_all(&v.to_le_bytes())?,
289 PrimitiveValue::DateTime(v) => self.writer.write_all(&v.to_le_bytes())?,
290 PrimitiveValue::UInt16(v) => self.writer.write_all(&v.to_le_bytes())?,
291 PrimitiveValue::UInt32(v) => self.writer.write_all(&v.to_le_bytes())?,
292 PrimitiveValue::UInt64(v) => self.writer.write_all(&v.to_le_bytes())?,
293 PrimitiveValue::String(s) => self.write_length_prefixed_string(s)?,
294 PrimitiveValue::Decimal(s) => {
295 let bytes = hex::decode(s).map_err(|e| {
296 crate::error::Error::Custom(format!("Invalid hex for Decimal: {}", e))
297 })?;
298 if bytes.len() != 16 {
299 return Err(crate::error::Error::Custom(format!(
300 "Decimal must be 16 bytes, got {}",
301 bytes.len()
302 )));
303 }
304 self.writer.write_all(&bytes)?;
305 }
306 PrimitiveValue::Null => {} }
308 Ok(())
309 }
310
311 fn write_object_value(&mut self, val: &ObjectValue) -> Result<()> {
312 match val {
313 ObjectValue::Primitive(p) => {
314 if let PrimitiveValue::Null = p {
315 self.write_u8(RecordType::ObjectNull as u8)?;
323 } else {
324 self.write_primitive_value(p)?;
325 }
326 }
327 ObjectValue::Record(r) => {
328 self.encode(r)?;
329 }
330 }
331 Ok(())
332 }
333}