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 F32, F64, C64, R64, Index,
202 String, Bool, Atom,
203 Set, Map, Table, Tuple, Record, Enum,
204 VariableDefine, VariableAssign, KindDefine,
205 KindAnnotation, SubscriptRange, SubscriptFormula,
206 RangeInclusive, RangeExclusive,
207 DotIndexing, Swizzle, LogicalIndexing,
208 Matrix1, Matrix2, Matrix3, Matrix4,
209 Matrix2x3, Matrix3x2,
210 RowVector2, RowVector3, RowVector4,
211 Vector2, Vector3, Vector4,
212 VectorD, MatrixD, RowVectorD,
213 HorzCat, VertCat,
214 Compiler, PrettyPrint, Serde,
215 MatMul, Transpose, Dot, Cross,
216 Add, Sub, Mul, Div, Exp, Mod, Neg, OpAssign,
217 LT, LTE, GT, GTE, EQ, NEQ,
218 And, Or, Xor, Not,
219 Convert, Assign, Access,
220 Functions, Formulas,
221 Custom = 0xFFFF,
222}
223
224impl FeatureKind {
225
226 pub fn as_string(&self) -> String {
227 match self {
228 FeatureKind::I8 => "i8".to_string(),
229 FeatureKind::I16 => "i16".to_string(),
230 FeatureKind::I32 => "i32".to_string(),
231 FeatureKind::I64 => "i64".to_string(),
232 FeatureKind::I128 => "i128".to_string(),
233 FeatureKind::U8 => "u8".to_string(),
234 FeatureKind::U16 => "u16".to_string(),
235 FeatureKind::U32 => "u32".to_string(),
236 FeatureKind::U64 => "u64".to_string(),
237 FeatureKind::U128 => "u128".to_string(),
238 FeatureKind::F32 => "f32".to_string(),
239 FeatureKind::F64 => "f64".to_string(),
240 FeatureKind::C64 => "c64".to_string(),
241 FeatureKind::R64 => "r64".to_string(),
242 FeatureKind::Index => "index".to_string(),
243 FeatureKind::String => "string".to_string(),
244 FeatureKind::Bool => "bool".to_string(),
245 FeatureKind::Atom => "atom".to_string(),
246 FeatureKind::Set => "set".to_string(),
247 FeatureKind::Map => "map".to_string(),
248 FeatureKind::Table => "table".to_string(),
249 FeatureKind::Tuple => "tuple".to_string(),
250 FeatureKind::Record => "record".to_string(),
251 FeatureKind::Enum => "enum".to_string(),
252 FeatureKind::VariableDefine => "variable_define".to_string(),
253 FeatureKind::VariableAssign => "variable_assign".to_string(),
254 FeatureKind::KindDefine => "kind_define".to_string(),
255 FeatureKind::KindAnnotation => "kind_annotation".to_string(),
256 FeatureKind::SubscriptRange => "subscript_range".to_string(),
257 FeatureKind::SubscriptFormula => "subscript_formula".to_string(),
258 FeatureKind::RangeInclusive => "range_inclusive".to_string(),
259 FeatureKind::RangeExclusive => "range_exclusive".to_string(),
260 FeatureKind::DotIndexing => "dot_indexing".to_string(),
261 FeatureKind::Swizzle => "swizzle".to_string(),
262 FeatureKind::LogicalIndexing => "logical_indexing".to_string(),
263 FeatureKind::Matrix1 => "matrix1".to_string(),
264 FeatureKind::Matrix2 => "matrix2".to_string(),
265 FeatureKind::Matrix3 => "matrix3".to_string(),
266 FeatureKind::Matrix4 => "matrix4".to_string(),
267 FeatureKind::Matrix2x3 => "matrix2x3".to_string(),
268 FeatureKind::Matrix3x2 => "matrix3x2".to_string(),
269 FeatureKind::RowVector2 => "row_vector2".to_string(),
270 FeatureKind::RowVector3 => "row_vector3".to_string(),
271 FeatureKind::RowVector4 => "row_vector4".to_string(),
272 FeatureKind::Vector2 => "vector2".to_string(),
273 FeatureKind::Vector3 => "vector3".to_string(),
274 FeatureKind::Vector4 => "vector4".to_string(),
275 FeatureKind::VectorD => "vectord".to_string(),
276 FeatureKind::MatrixD => "matrixd".to_string(),
277 FeatureKind::RowVectorD => "row_vectord".to_string(),
278 FeatureKind::HorzCat => "matrix_horzcat".to_string(),
279 FeatureKind::VertCat => "matrix_vertcat".to_string(),
280 FeatureKind::Compiler => "compiler".to_string(),
281 FeatureKind::PrettyPrint => "pretty_print".to_string(),
282 FeatureKind::Serde => "serde".to_string(),
283 FeatureKind::MatMul => "matrix_matmul".to_string(),
284 FeatureKind::Transpose => "matrix_transpose".to_string(),
285 FeatureKind::Dot => "matrix_dot".to_string(),
286 FeatureKind::Cross => "matrix_cross".to_string(),
287 FeatureKind::Add => "math_add".to_string(),
288 FeatureKind::Sub => "math_sub".to_string(),
289 FeatureKind::Mul => "math_mul".to_string(),
290 FeatureKind::Div => "math_div".to_string(),
291 FeatureKind::Exp => "math_exp".to_string(),
292 FeatureKind::Mod => "math_mod".to_string(),
293 FeatureKind::Neg => "math_neg".to_string(),
294 FeatureKind::OpAssign => "math_opassign".to_string(),
295 FeatureKind::LT => "compare_lt".to_string(),
296 FeatureKind::LTE => "compare_lte".to_string(),
297 FeatureKind::GT => "compare_gt".to_string(),
298 FeatureKind::GTE => "compare_gte".to_string(),
299 FeatureKind::EQ => "compare_eq".to_string(),
300 FeatureKind::NEQ => "compare_neq".to_string(),
301 FeatureKind::And => "logic_and".to_string(),
302 FeatureKind::Or => "logic_or".to_string(),
303 FeatureKind::Xor => "logic_xor".to_string(),
304 FeatureKind::Not => "logic_not".to_string(),
305 FeatureKind::Convert => "convert".to_string(),
306 FeatureKind::Assign => "assign".to_string(),
307 FeatureKind::Access => "access".to_string(),
308 FeatureKind::Functions => "functions".to_string(),
309 FeatureKind::Formulas => "formulas".to_string(),
310 FeatureKind::Custom => "custom".to_string(),
311 }
312 }
313}
314
315#[derive(Debug, Clone, PartialEq, Eq, Hash)]
316pub enum FeatureFlag {
317 Builtin(FeatureKind),
318 Custom(u64),
319}
320
321impl FeatureFlag {
322
323 pub fn as_string(&self) -> String {
324 match self {
325 FeatureFlag::Builtin(f) => f.as_string(),
326 FeatureFlag::Custom(c) => format!("custom({})", c),
327 }
328 }
329}
330
331impl FeatureFlag {
332 pub fn as_u64(&self) -> u64 {
333 match self {
334 FeatureFlag::Builtin(f) => *f as u64,
335 FeatureFlag::Custom(c) => *c,
336 }
337 }
338}
339
340#[repr(u16)]
344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
345#[derive(Debug, Clone, Copy, Eq, PartialEq)]
346pub enum TypeTag {
347 U8=1, U16, U32, U64, U128, I8, I16, I32, I64, I128,
348 F32, F64, C64, R64, String, Bool, Id, Index, Empty, Any,
349 MatrixU8, MatrixU16, MatrixU32, MatrixU64, MatrixU128,
350 MatrixI8, MatrixI16, MatrixI32, MatrixI64, MatrixI128,
351 MatrixF32, MatrixF64, MatrixC64, MatrixR64, MatrixBool,
352 MatrixString, MatrixIndex,
353 EnumTag, Record, Map, Atom,
354 Table, Tuple, Reference, Set, OptionT,
355}
356
357impl TypeTag {
358 pub fn from_u16(tag: u16) -> Option<Self> {
359 match tag {
360 1 => Some(TypeTag::U8), 2 => Some(TypeTag::U16), 3 => Some(TypeTag::U32), 4 => Some(TypeTag::U64), 5 => Some(TypeTag::U128),
361 6 => Some(TypeTag::I8), 7 => Some(TypeTag::I16), 8 => Some(TypeTag::I32), 9 => Some(TypeTag::I64), 10 => Some(TypeTag::I128),
362 11 => Some(TypeTag::F32), 12 => Some(TypeTag::F64), 13 => Some(TypeTag::C64), 14 => Some(TypeTag::R64),
363 15 => Some(TypeTag::String), 16 => Some(TypeTag::Bool), 17 => Some(TypeTag::Id), 18 => Some(TypeTag::Index), 19 => Some(TypeTag::Empty), 20 => Some(TypeTag::Any),
364 21 => Some(TypeTag::MatrixU8), 22 => Some(TypeTag::MatrixU16), 23 => Some(TypeTag::MatrixU32), 24 => Some(TypeTag::MatrixU64), 25 => Some(TypeTag::MatrixU128),
365 26 => Some(TypeTag::MatrixI8), 27 => Some(TypeTag::MatrixI16), 28 => Some(TypeTag::MatrixI32), 29 => Some(TypeTag::MatrixI64), 30 => Some(TypeTag::MatrixI128),
366 31 => Some(TypeTag::MatrixF32), 32 => Some(TypeTag::MatrixF64), 33 => Some(TypeTag::MatrixC64), 34 => Some(TypeTag::MatrixR64), 35 => Some(TypeTag::MatrixBool),
367 36 => Some(TypeTag::MatrixString), 37 => Some(TypeTag::MatrixIndex),
368 38 => Some(TypeTag::EnumTag), 39 => Some(TypeTag::Record), 40 => Some(TypeTag::Map), 41 => Some(TypeTag::Atom),
369 42 => Some(TypeTag::Table), 43 => Some(TypeTag::Tuple), 44 => Some(TypeTag::Reference), 45 => Some(TypeTag::Set), 46 => Some(TypeTag::OptionT),
370 _ => None,
371 }
372 }
373}
374
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376#[derive(Debug, Clone, Eq, PartialEq)]
377pub struct TypeEntry {
378 pub tag: TypeTag,
379 pub bytes: Vec<u8>,
380}
381impl TypeEntry {
382 pub fn byte_len(&self) -> u64 {
383 2 + self.bytes.len() as u64
384 }
385}
386
387pub type TypeId = u32;
388
389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
390#[derive(Default, Debug, Clone, Eq, PartialEq)]
391pub struct TypeSection {
392 pub interner: HashMap<ValueKind, TypeId>,
393 pub entries: Vec<TypeEntry>, }
395
396impl TypeSection {
397
398 pub fn new() -> Self {
399 Self { interner: HashMap::new(), entries: Vec::new() }
400 }
401
402 pub fn get_or_intern(&mut self, vk: &ValueKind) -> TypeId {
403 if let Some(id) = self.interner.get(vk) { return *id; }
404 let (tag, mut bytes) = encode_value_kind(self, vk);
406 let id = self.entries.len() as u32;
407 self.entries.push(TypeEntry { tag, bytes });
408 self.interner.insert(vk.clone(), id);
409 id
410 }
411
412 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
413 w.write_u32::<LittleEndian>(self.entries.len() as u32)?;
414 for e in &self.entries {
415 w.write_u16::<LittleEndian>(e.tag as u16)?;
416 w.write_u16::<LittleEndian>(0)?;
417 w.write_u32::<LittleEndian>(1)?;
418 w.write_u32::<LittleEndian>(e.bytes.len() as u32)?;
419 w.write_all(&e.bytes)?;
420 }
421 Ok(())
422 }
423
424 pub fn byte_len(&self) -> u64 {
425 4 + self.entries.iter().map(|e| 12 + e.bytes.len() as u64).sum::<u64>()
426 }
427}
428
429#[repr(u8)]
433#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
434#[derive(Debug, Clone, Copy, Eq, PartialEq)]
435pub enum ConstEncoding {
436 Inline = 1
437}
438
439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
440#[derive(Debug, Clone, Eq, PartialEq)]
441pub struct ConstEntry {
442 pub type_id: u32,
443 pub enc: ConstEncoding,
444 pub align: u8,
445 pub flags: u8,
446 pub reserved:u16,
447 pub offset: u64,
448 pub length: u64,
449}
450
451impl ConstEntry {
452 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
453 w.write_u32::<LittleEndian>(self.type_id)?;
454 w.write_u8(self.enc as u8)?;
455 w.write_u8(self.align)?;
456 w.write_u8(self.flags)?;
457 w.write_u8(0)?; w.write_u64::<LittleEndian>(self.offset)?;
459 w.write_u64::<LittleEndian>(self.length)?;
460 Ok(())
461 }
462 pub fn byte_len() -> u64 { 4 + 1 + 1 + 1 + 1 + 8 + 8 } }
464
465pub struct SymbolEntry {
469 pub id: u64, pub mutable: bool,
471 pub reg: Register, }
473
474impl SymbolEntry {
475
476 pub fn new(id: u64, mutable: bool, reg: Register) -> Self {
477 Self { id, mutable, reg }
478 }
479
480 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
481 w.write_u64::<LittleEndian>(self.id)?;
482 w.write_u8(if self.mutable { 1 } else { 0 })?;
483 w.write_u32::<LittleEndian>(self.reg)?;
484 Ok(())
485 }
486}
487
488#[repr(u8)]
492#[derive(Debug, Clone, Copy, PartialEq, Eq)]
493pub enum OpCode {
494 ConstLoad = 0x01,
495 NullOp = 0x10,
496 Unop = 0x20,
497 Binop = 0x30,
498 Ternop = 0x40,
499 Quadop = 0x50,
500 VarArg = 0x60,
501 Return = 0xFF,
502}
503
504impl OpCode {
505 pub fn from_u8(num: u8) -> Option<OpCode> {
506 match num {
507 0x01 => Some(OpCode::ConstLoad),
508 0x10 => Some(OpCode::NullOp),
509 0x20 => Some(OpCode::Unop),
510 0x30 => Some(OpCode::Binop),
511 0x40 => Some(OpCode::Ternop),
512 0x50 => Some(OpCode::Quadop),
513 0x60 => Some(OpCode::VarArg),
514 0xFF => Some(OpCode::Return),
515 _ => None,
516 }
517 }
518}
519
520#[derive(Debug, Clone)]
521pub enum EncodedInstr {
522 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 }, }
531
532impl EncodedInstr {
533 pub fn byte_len(&self) -> u64 {
534 match self {
535 EncodedInstr::ConstLoad{..} => 1 + 4 + 4,
536 EncodedInstr::NullOp{..} => 1 + 8 + 4,
537 EncodedInstr::UnOp{..} => 1 + 8 + 4 + 4,
538 EncodedInstr::BinOp{..} => 1 + 8 + 4 + 4 + 4,
539 EncodedInstr::TernOp{..} => 1 + 8 + 4 + 4 + 4 + 4,
540 EncodedInstr::QuadOp{..} => 1 + 8 + 4 + 4 + 4 + 4 + 4,
541 EncodedInstr::VarArg{ args, .. } => 1 + 8 + 4 + 4 + (4 * args.len() as u64),
542 EncodedInstr::Ret{..} => 1 + 4,
543 }
544 }
545 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
546 match self {
547 EncodedInstr::ConstLoad{ dst, const_id } => {
548 w.write_u8(OpCode::ConstLoad as u8)?;
549 w.write_u32::<LittleEndian>(*dst)?;
550 w.write_u32::<LittleEndian>(*const_id)?;
551 }
552 EncodedInstr::NullOp{ fxn_id, dst } => {
553 w.write_u8(OpCode::NullOp as u8)?;
554 w.write_u64::<LittleEndian>(*fxn_id)?;
555 w.write_u32::<LittleEndian>(*dst)?;
556 }
557 EncodedInstr::UnOp{ fxn_id, dst, src } => {
558 w.write_u8(OpCode::Unop as u8)?;
559 w.write_u64::<LittleEndian>(*fxn_id)?;
560 w.write_u32::<LittleEndian>(*dst)?;
561 w.write_u32::<LittleEndian>(*src)?;
562 }
563 EncodedInstr::BinOp{ fxn_id, dst, lhs, rhs } => {
564 w.write_u8(OpCode::Binop as u8)?;
565 w.write_u64::<LittleEndian>(*fxn_id)?;
566 w.write_u32::<LittleEndian>(*dst)?;
567 w.write_u32::<LittleEndian>(*lhs)?;
568 w.write_u32::<LittleEndian>(*rhs)?;
569 }
570 EncodedInstr::TernOp{ fxn_id, dst, a, b, c } => {
571 w.write_u8(OpCode::Ternop as u8)?;
572 w.write_u64::<LittleEndian>(*fxn_id)?;
573 w.write_u32::<LittleEndian>(*dst)?;
574 w.write_u32::<LittleEndian>(*a)?;
575 w.write_u32::<LittleEndian>(*b)?;
576 w.write_u32::<LittleEndian>(*c)?;
577 }
578 EncodedInstr::QuadOp{ fxn_id, dst, a, b, c, d } => {
579 w.write_u8(OpCode::Quadop as u8)?;
580 w.write_u64::<LittleEndian>(*fxn_id)?;
581 w.write_u32::<LittleEndian>(*dst)?;
582 w.write_u32::<LittleEndian>(*a)?;
583 w.write_u32::<LittleEndian>(*b)?;
584 w.write_u32::<LittleEndian>(*c)?;
585 w.write_u32::<LittleEndian>(*d)?;
586 }
587 EncodedInstr::VarArg{ fxn_id, dst, args } => {
588 w.write_u8(OpCode::VarArg as u8)?;
589 w.write_u64::<LittleEndian>(*fxn_id)?;
590 w.write_u32::<LittleEndian>(*dst)?;
591 w.write_u32::<LittleEndian>(args.len() as u32)?;
592 for a in args {
593 w.write_u32::<LittleEndian>(*a)?;
594 }
595 }
596 EncodedInstr::Ret{ src } => {
597 w.write_u8(OpCode::Return as u8)?;
598 w.write_u32::<LittleEndian>(*src)?;
599 }
600 }
601 Ok(())
602 }
603}
604
605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
609#[derive(Debug, Clone, Eq, PartialEq)]
610pub struct DictEntry {
611 pub id: u64, pub name: String, }
614
615impl DictEntry {
616 pub fn new(id: u64, name: &str) -> Self {
617 Self { id, name: name.to_string() }
618 }
619
620 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
621 w.write_u64::<LittleEndian>(self.id)?;
622 let name_bytes = self.name.as_bytes();
623 w.write_u32::<LittleEndian>(name_bytes.len() as u32)?;
624 w.write_all(name_bytes)?;
625 Ok(())
626 }
627}
628
629