1use crate::*;
2use super::*;
3
4#[repr(C)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, Clone, Eq, PartialEq)]
22pub struct ByteCodeHeader {
23 pub magic: [u8; 4], pub version: u8, pub mech_ver: u16, pub flags: u16, pub reg_count: u32, pub instr_count: u32, pub feature_count: u32, pub feature_off: u64, pub types_count: u32, pub types_off: u64, pub const_count: u32, pub const_tbl_off: u64, pub const_tbl_len: u64, pub const_blob_off: u64, pub const_blob_len: u64, pub symbols_len: u64, pub symbols_off: u64, pub instr_off: u64, pub instr_len: u64, pub dict_off: u64, pub dict_len: u64, pub reserved: u32, }
53
54impl ByteCodeHeader {
55 pub const HEADER_SIZE: usize = 4 + 1 + 2 + 2 + 4 + 4 + 4 + 8 + 4 + 8 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 4; pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
82 w.write_all(&self.magic)?;
84
85 w.write_u8(self.version)?;
87 w.write_u16::<LittleEndian>(self.mech_ver)?;
88 w.write_u16::<LittleEndian>(self.flags)?;
89
90 w.write_u32::<LittleEndian>(self.reg_count)?;
92 w.write_u32::<LittleEndian>(self.instr_count)?;
93
94 w.write_u32::<LittleEndian>(self.feature_count)?;
96 w.write_u64::<LittleEndian>(self.feature_off)?;
97
98 w.write_u32::<LittleEndian>(self.types_count)?;
100 w.write_u64::<LittleEndian>(self.types_off)?;
101
102 w.write_u32::<LittleEndian>(self.const_count)?;
104 w.write_u64::<LittleEndian>(self.const_tbl_off)?;
105 w.write_u64::<LittleEndian>(self.const_tbl_len)?;
106 w.write_u64::<LittleEndian>(self.const_blob_off)?;
107 w.write_u64::<LittleEndian>(self.const_blob_len)?;
108
109 w.write_u64::<LittleEndian>(self.symbols_len)?;
111 w.write_u64::<LittleEndian>(self.symbols_off)?;
112
113 w.write_u64::<LittleEndian>(self.instr_off)?;
115 w.write_u64::<LittleEndian>(self.instr_len)?;
116
117 w.write_u64::<LittleEndian>(self.dict_off)?;
119 w.write_u64::<LittleEndian>(self.dict_len)?;
120
121 w.write_u32::<LittleEndian>(self.reserved)?;
123 Ok(())
124 }
125
126 pub fn read_from(r: &mut impl Read) -> MResult<Self> {
128 let mut magic = [0u8; 4];
129 r.read_exact(&mut magic)?;
130
131 let version = r.read_u8()?;
132 let mech_ver = r.read_u16::<LittleEndian>()?;
133 let flags = r.read_u16::<LittleEndian>()?;
134
135 let reg_count = r.read_u32::<LittleEndian>()?;
136 let instr_count = r.read_u32::<LittleEndian>()?;
137
138 let feature_count = r.read_u32::<LittleEndian>()?;
139 let feature_off = r.read_u64::<LittleEndian>()?;
140
141 let types_count = r.read_u32::<LittleEndian>()?;
142 let types_off = r.read_u64::<LittleEndian>()?;
143
144 let const_count = r.read_u32::<LittleEndian>()?;
145 let const_tbl_off = r.read_u64::<LittleEndian>()?;
146 let const_tbl_len = r.read_u64::<LittleEndian>()?;
147 let const_blob_off = r.read_u64::<LittleEndian>()?;
148 let const_blob_len = r.read_u64::<LittleEndian>()?;
149
150 let symbols_len = r.read_u64::<LittleEndian>()?;
151 let symbols_off = r.read_u64::<LittleEndian>()?;
152
153 let instr_off = r.read_u64::<LittleEndian>()?;
154 let instr_len = r.read_u64::<LittleEndian>()?;
155
156 let dict_off = r.read_u64::<LittleEndian>()?;
157 let dict_len = r.read_u64::<LittleEndian>()?;
158
159 let reserved = r.read_u32::<LittleEndian>()?;
160
161 Ok(Self {
162 magic,
163 version,
164 mech_ver,
165 flags,
166 reg_count,
167 instr_count,
168 feature_count,
169 feature_off,
170 types_count,
171 types_off,
172 const_count,
173 const_tbl_off,
174 const_tbl_len,
175 const_blob_off,
176 const_blob_len,
177 instr_off,
178 instr_len,
179 symbols_len,
180 symbols_off,
181 dict_off,
182 dict_len,
183 reserved,
184 })
185 }
186
187 pub fn validate_magic(&self, expected: &[u8;4]) -> bool {
189 &self.magic == expected
190 }
191}
192
193#[repr(u16)]
197#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
198pub enum FeatureKind {
199 I8=1, I16, I32, I64, I128,
200 U8, U16, U32, U64, U128,
201
202 F32, F64, C64, R64, Index,
203 String, Bool, Atom, Set, Map,
204
205 Table, Tuple, Record, Enum,
206 VariableDefine, VariableAssign, KindDefine,
207 KindAnnotation, SubscriptRange, SubscriptFormula,
208
209 RangeInclusive, RangeExclusive,
210 DotIndexing, Swizzle, LogicalIndexing,
211 Matrix1, Matrix2, Matrix3, Matrix4, Matrix2x3,
212
213 Matrix3x2, RowVector2, RowVector3, RowVector4,
214 Vector2, Vector3, Vector4, VectorD, MatrixD, RowVectorD,
215
216 HorzCat, VertCat,
217 Compiler, PrettyPrint, Serde,
218 MatMul, Transpose, Dot, Cross, Add,
219
220 Sub, Mul, Div, Exp, Mod,
221 Neg, OpAssign, LT, LTE, GT,
222
223 GTE, EQ, NEQ, And, Or,
224 Xor, Not, Convert, Assign, Access,
225
226 Functions, Formulas,
227 Custom = 0xFFFF,
228}
229
230impl FeatureKind {
231
232 pub fn as_string(&self) -> String {
233 match self {
234 FeatureKind::I8 => "i8".to_string(),
235 FeatureKind::I16 => "i16".to_string(),
236 FeatureKind::I32 => "i32".to_string(),
237 FeatureKind::I64 => "i64".to_string(),
238 FeatureKind::I128 => "i128".to_string(),
239 FeatureKind::U8 => "u8".to_string(),
240 FeatureKind::U16 => "u16".to_string(),
241 FeatureKind::U32 => "u32".to_string(),
242 FeatureKind::U64 => "u64".to_string(),
243 FeatureKind::U128 => "u128".to_string(),
244 FeatureKind::F32 => "f32".to_string(),
245 FeatureKind::F64 => "f64".to_string(),
246 FeatureKind::C64 => "c64".to_string(),
247 FeatureKind::R64 => "r64".to_string(),
248 FeatureKind::Index => "index".to_string(),
249 FeatureKind::String => "string".to_string(),
250 FeatureKind::Bool => "bool".to_string(),
251 FeatureKind::Atom => "atom".to_string(),
252 FeatureKind::Set => "set".to_string(),
253 FeatureKind::Map => "map".to_string(),
254 FeatureKind::Table => "table".to_string(),
255 FeatureKind::Tuple => "tuple".to_string(),
256 FeatureKind::Record => "record".to_string(),
257 FeatureKind::Enum => "enum".to_string(),
258 FeatureKind::VariableDefine => "variable_define".to_string(),
259 FeatureKind::VariableAssign => "variable_assign".to_string(),
260 FeatureKind::KindDefine => "kind_define".to_string(),
261 FeatureKind::KindAnnotation => "kind_annotation".to_string(),
262 FeatureKind::SubscriptRange => "subscript_range".to_string(),
263 FeatureKind::SubscriptFormula => "subscript_formula".to_string(),
264 FeatureKind::RangeInclusive => "range_inclusive".to_string(),
265 FeatureKind::RangeExclusive => "range_exclusive".to_string(),
266 FeatureKind::DotIndexing => "dot_indexing".to_string(),
267 FeatureKind::Swizzle => "swizzle".to_string(),
268 FeatureKind::LogicalIndexing => "logical_indexing".to_string(),
269 FeatureKind::Matrix1 => "matrix1".to_string(),
270 FeatureKind::Matrix2 => "matrix2".to_string(),
271 FeatureKind::Matrix3 => "matrix3".to_string(),
272 FeatureKind::Matrix4 => "matrix4".to_string(),
273 FeatureKind::Matrix2x3 => "matrix2x3".to_string(),
274 FeatureKind::Matrix3x2 => "matrix3x2".to_string(),
275 FeatureKind::RowVector2 => "row_vector2".to_string(),
276 FeatureKind::RowVector3 => "row_vector3".to_string(),
277 FeatureKind::RowVector4 => "row_vector4".to_string(),
278 FeatureKind::Vector2 => "vector2".to_string(),
279 FeatureKind::Vector3 => "vector3".to_string(),
280 FeatureKind::Vector4 => "vector4".to_string(),
281 FeatureKind::VectorD => "vectord".to_string(),
282 FeatureKind::MatrixD => "matrixd".to_string(),
283 FeatureKind::RowVectorD => "row_vectord".to_string(),
284 FeatureKind::HorzCat => "matrix_horzcat".to_string(),
285 FeatureKind::VertCat => "matrix_vertcat".to_string(),
286 FeatureKind::Compiler => "compiler".to_string(),
287 FeatureKind::PrettyPrint => "pretty_print".to_string(),
288 FeatureKind::Serde => "serde".to_string(),
289 FeatureKind::MatMul => "matrix_matmul".to_string(),
290 FeatureKind::Transpose => "matrix_transpose".to_string(),
291 FeatureKind::Dot => "matrix_dot".to_string(),
292 FeatureKind::Cross => "matrix_cross".to_string(),
293 FeatureKind::Add => "math_add".to_string(),
294 FeatureKind::Sub => "math_sub".to_string(),
295 FeatureKind::Mul => "math_mul".to_string(),
296 FeatureKind::Div => "math_div".to_string(),
297 FeatureKind::Exp => "math_exp".to_string(),
298 FeatureKind::Mod => "math_mod".to_string(),
299 FeatureKind::Neg => "math_neg".to_string(),
300 FeatureKind::OpAssign => "math_opassign".to_string(),
301 FeatureKind::LT => "compare_lt".to_string(),
302 FeatureKind::LTE => "compare_lte".to_string(),
303 FeatureKind::GT => "compare_gt".to_string(),
304 FeatureKind::GTE => "compare_gte".to_string(),
305 FeatureKind::EQ => "compare_eq".to_string(),
306 FeatureKind::NEQ => "compare_neq".to_string(),
307 FeatureKind::And => "logic_and".to_string(),
308 FeatureKind::Or => "logic_or".to_string(),
309 FeatureKind::Xor => "logic_xor".to_string(),
310 FeatureKind::Not => "logic_not".to_string(),
311 FeatureKind::Convert => "convert".to_string(),
312 FeatureKind::Assign => "assign".to_string(),
313 FeatureKind::Access => "access".to_string(),
314 FeatureKind::Functions => "functions".to_string(),
315 FeatureKind::Formulas => "formulas".to_string(),
316 FeatureKind::Custom => "custom".to_string(),
317 }
318 }
319}
320
321#[derive(Debug, Clone, PartialEq, Eq, Hash)]
322pub enum FeatureFlag {
323 Builtin(FeatureKind),
324 Custom(u64),
325}
326
327impl FeatureFlag {
328
329 pub fn as_string(&self) -> String {
330 match self {
331 FeatureFlag::Builtin(f) => f.as_string(),
332 FeatureFlag::Custom(c) => format!("custom({})", c),
333 }
334 }
335}
336
337impl FeatureFlag {
338 pub fn as_u64(&self) -> u64 {
339 match self {
340 FeatureFlag::Builtin(f) => *f as u64,
341 FeatureFlag::Custom(c) => *c,
342 }
343 }
344}
345
346#[repr(u16)]
350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
351#[derive(Debug, Clone, Copy, Eq, PartialEq)]
352pub enum TypeTag {
353 U8=1, U16, U32, U64, U128, I8, I16, I32, I64, I128,
354 F32, F64, C64, R64, String, Bool, Id, Index, Empty, Any,
355 MatrixU8, MatrixU16, MatrixU32, MatrixU64, MatrixU128,
356 MatrixI8, MatrixI16, MatrixI32, MatrixI64, MatrixI128,
357 MatrixF32, MatrixF64, MatrixC64, MatrixR64, MatrixBool,
358 MatrixString, MatrixIndex,
359 EnumTag, Record, Map, Atom,
360 Table, Tuple, Reference, Set, OptionT,
361}
362
363impl TypeTag {
364 pub fn from_u16(tag: u16) -> Option<Self> {
365 match tag {
366 1 => Some(TypeTag::U8), 2 => Some(TypeTag::U16), 3 => Some(TypeTag::U32), 4 => Some(TypeTag::U64), 5 => Some(TypeTag::U128),
367 6 => Some(TypeTag::I8), 7 => Some(TypeTag::I16), 8 => Some(TypeTag::I32), 9 => Some(TypeTag::I64), 10 => Some(TypeTag::I128),
368 11 => Some(TypeTag::F32), 12 => Some(TypeTag::F64), 13 => Some(TypeTag::C64), 14 => Some(TypeTag::R64),
369 15 => Some(TypeTag::String), 16 => Some(TypeTag::Bool), 17 => Some(TypeTag::Id), 18 => Some(TypeTag::Index), 19 => Some(TypeTag::Empty), 20 => Some(TypeTag::Any),
370 21 => Some(TypeTag::MatrixU8), 22 => Some(TypeTag::MatrixU16), 23 => Some(TypeTag::MatrixU32), 24 => Some(TypeTag::MatrixU64), 25 => Some(TypeTag::MatrixU128),
371 26 => Some(TypeTag::MatrixI8), 27 => Some(TypeTag::MatrixI16), 28 => Some(TypeTag::MatrixI32), 29 => Some(TypeTag::MatrixI64), 30 => Some(TypeTag::MatrixI128),
372 31 => Some(TypeTag::MatrixF32), 32 => Some(TypeTag::MatrixF64), 33 => Some(TypeTag::MatrixC64), 34 => Some(TypeTag::MatrixR64), 35 => Some(TypeTag::MatrixBool),
373 36 => Some(TypeTag::MatrixString), 37 => Some(TypeTag::MatrixIndex),
374 38 => Some(TypeTag::EnumTag), 39 => Some(TypeTag::Record), 40 => Some(TypeTag::Map), 41 => Some(TypeTag::Atom),
375 42 => Some(TypeTag::Table), 43 => Some(TypeTag::Tuple), 44 => Some(TypeTag::Reference), 45 => Some(TypeTag::Set), 46 => Some(TypeTag::OptionT),
376 _ => None,
377 }
378 }
379}
380
381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
382#[derive(Debug, Clone, Eq, PartialEq)]
383pub struct TypeEntry {
384 pub tag: TypeTag,
385 pub bytes: Vec<u8>,
386}
387impl TypeEntry {
388 pub fn byte_len(&self) -> u64 {
389 2 + self.bytes.len() as u64
390 }
391}
392
393pub type TypeId = u32;
394
395#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
396#[derive(Default, Debug, Clone, Eq, PartialEq)]
397pub struct TypeSection {
398 pub interner: HashMap<ValueKind, TypeId>,
399 pub entries: Vec<TypeEntry>, }
401
402impl TypeSection {
403
404 pub fn new() -> Self {
405 Self { interner: HashMap::new(), entries: Vec::new() }
406 }
407
408 pub fn get_or_intern(&mut self, vk: &ValueKind) -> TypeId {
409 if let Some(id) = self.interner.get(vk) { return *id; }
410 let (tag, mut bytes) = encode_value_kind(self, vk);
412 let id = self.entries.len() as u32;
413 self.entries.push(TypeEntry { tag, bytes });
414 self.interner.insert(vk.clone(), id);
415 id
416 }
417
418 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
419 w.write_u32::<LittleEndian>(self.entries.len() as u32)?;
420 for e in &self.entries {
421 w.write_u16::<LittleEndian>(e.tag as u16)?;
422 w.write_u16::<LittleEndian>(0)?;
423 w.write_u32::<LittleEndian>(1)?;
424 w.write_u32::<LittleEndian>(e.bytes.len() as u32)?;
425 w.write_all(&e.bytes)?;
426 }
427 Ok(())
428 }
429
430 pub fn byte_len(&self) -> u64 {
431 4 + self.entries.iter().map(|e| 12 + e.bytes.len() as u64).sum::<u64>()
432 }
433}
434
435#[repr(u8)]
439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
440#[derive(Debug, Clone, Copy, Eq, PartialEq)]
441pub enum ConstEncoding {
442 Inline = 1
443}
444
445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
446#[derive(Debug, Clone, Eq, PartialEq)]
447pub struct ConstEntry {
448 pub type_id: u32,
449 pub enc: ConstEncoding,
450 pub align: u8,
451 pub flags: u8,
452 pub reserved:u16,
453 pub offset: u64,
454 pub length: u64,
455}
456
457impl ConstEntry {
458 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
459 w.write_u32::<LittleEndian>(self.type_id)?;
460 w.write_u8(self.enc as u8)?;
461 w.write_u8(self.align)?;
462 w.write_u8(self.flags)?;
463 w.write_u8(0)?; w.write_u64::<LittleEndian>(self.offset)?;
465 w.write_u64::<LittleEndian>(self.length)?;
466 Ok(())
467 }
468 pub fn byte_len() -> u64 { 4 + 1 + 1 + 1 + 1 + 8 + 8 } }
470
471pub struct SymbolEntry {
475 pub id: u64, pub mutable: bool,
477 pub reg: Register, }
479
480impl SymbolEntry {
481
482 pub fn new(id: u64, mutable: bool, reg: Register) -> Self {
483 Self { id, mutable, reg }
484 }
485
486 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
487 w.write_u64::<LittleEndian>(self.id)?;
488 w.write_u8(if self.mutable { 1 } else { 0 })?;
489 w.write_u32::<LittleEndian>(self.reg)?;
490 Ok(())
491 }
492}
493
494#[repr(u8)]
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
499pub enum OpCode {
500 ConstLoad = 0x01,
501 NullOp = 0x10,
502 Unop = 0x20,
503 Binop = 0x30,
504 Ternop = 0x40,
505 Quadop = 0x50,
506 VarArg = 0x60,
507 Return = 0xFF,
508}
509
510impl OpCode {
511 pub fn from_u8(num: u8) -> Option<OpCode> {
512 match num {
513 0x01 => Some(OpCode::ConstLoad),
514 0x10 => Some(OpCode::NullOp),
515 0x20 => Some(OpCode::Unop),
516 0x30 => Some(OpCode::Binop),
517 0x40 => Some(OpCode::Ternop),
518 0x50 => Some(OpCode::Quadop),
519 0x60 => Some(OpCode::VarArg),
520 0xFF => Some(OpCode::Return),
521 _ => None,
522 }
523 }
524}
525
526#[derive(Debug, Clone)]
527pub enum EncodedInstr {
528 ConstLoad { dst: u32, const_id: u32 }, NullOp { fxn_id: u64, dst: u32 }, UnOp { fxn_id: u64, dst: u32, src: u32 }, BinOp { fxn_id: u64, dst: u32, lhs: u32, rhs: u32 }, TernOp { fxn_id: u64, dst: u32, a: u32, b: u32, c: u32 }, QuadOp { fxn_id: u64, dst: u32, a: u32, b: u32, c: u32, d: u32 }, VarArg { fxn_id: u64, dst: u32, args: Vec<u32> }, Ret { src: u32 }, }
537
538impl EncodedInstr {
539 pub fn byte_len(&self) -> u64 {
540 match self {
541 EncodedInstr::ConstLoad{..} => 1 + 4 + 4,
542 EncodedInstr::NullOp{..} => 1 + 8 + 4,
543 EncodedInstr::UnOp{..} => 1 + 8 + 4 + 4,
544 EncodedInstr::BinOp{..} => 1 + 8 + 4 + 4 + 4,
545 EncodedInstr::TernOp{..} => 1 + 8 + 4 + 4 + 4 + 4,
546 EncodedInstr::QuadOp{..} => 1 + 8 + 4 + 4 + 4 + 4 + 4,
547 EncodedInstr::VarArg{ args, .. } => 1 + 8 + 4 + 4 + (4 * args.len() as u64),
548 EncodedInstr::Ret{..} => 1 + 4,
549 }
550 }
551 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
552 match self {
553 EncodedInstr::ConstLoad{ dst, const_id } => {
554 w.write_u8(OpCode::ConstLoad as u8)?;
555 w.write_u32::<LittleEndian>(*dst)?;
556 w.write_u32::<LittleEndian>(*const_id)?;
557 }
558 EncodedInstr::NullOp{ fxn_id, dst } => {
559 w.write_u8(OpCode::NullOp as u8)?;
560 w.write_u64::<LittleEndian>(*fxn_id)?;
561 w.write_u32::<LittleEndian>(*dst)?;
562 }
563 EncodedInstr::UnOp{ fxn_id, dst, src } => {
564 w.write_u8(OpCode::Unop as u8)?;
565 w.write_u64::<LittleEndian>(*fxn_id)?;
566 w.write_u32::<LittleEndian>(*dst)?;
567 w.write_u32::<LittleEndian>(*src)?;
568 }
569 EncodedInstr::BinOp{ fxn_id, dst, lhs, rhs } => {
570 w.write_u8(OpCode::Binop as u8)?;
571 w.write_u64::<LittleEndian>(*fxn_id)?;
572 w.write_u32::<LittleEndian>(*dst)?;
573 w.write_u32::<LittleEndian>(*lhs)?;
574 w.write_u32::<LittleEndian>(*rhs)?;
575 }
576 EncodedInstr::TernOp{ fxn_id, dst, a, b, c } => {
577 w.write_u8(OpCode::Ternop as u8)?;
578 w.write_u64::<LittleEndian>(*fxn_id)?;
579 w.write_u32::<LittleEndian>(*dst)?;
580 w.write_u32::<LittleEndian>(*a)?;
581 w.write_u32::<LittleEndian>(*b)?;
582 w.write_u32::<LittleEndian>(*c)?;
583 }
584 EncodedInstr::QuadOp{ fxn_id, dst, a, b, c, d } => {
585 w.write_u8(OpCode::Quadop as u8)?;
586 w.write_u64::<LittleEndian>(*fxn_id)?;
587 w.write_u32::<LittleEndian>(*dst)?;
588 w.write_u32::<LittleEndian>(*a)?;
589 w.write_u32::<LittleEndian>(*b)?;
590 w.write_u32::<LittleEndian>(*c)?;
591 w.write_u32::<LittleEndian>(*d)?;
592 }
593 EncodedInstr::VarArg{ fxn_id, dst, args } => {
594 w.write_u8(OpCode::VarArg as u8)?;
595 w.write_u64::<LittleEndian>(*fxn_id)?;
596 w.write_u32::<LittleEndian>(*dst)?;
597 w.write_u32::<LittleEndian>(args.len() as u32)?;
598 for a in args {
599 w.write_u32::<LittleEndian>(*a)?;
600 }
601 }
602 EncodedInstr::Ret{ src } => {
603 w.write_u8(OpCode::Return as u8)?;
604 w.write_u32::<LittleEndian>(*src)?;
605 }
606 }
607 Ok(())
608 }
609}
610
611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
615#[derive(Debug, Clone, Eq, PartialEq)]
616pub struct DictEntry {
617 pub id: u64, pub name: String, }
620
621impl DictEntry {
622 pub fn new(id: u64, name: &str) -> Self {
623 Self { id, name: name.to_string() }
624 }
625
626 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
627 w.write_u64::<LittleEndian>(self.id)?;
628 let name_bytes = self.name.as_bytes();
629 w.write_u32::<LittleEndian>(name_bytes.len() as u32)?;
630 w.write_all(name_bytes)?;
631 Ok(())
632 }
633}
634
635