Skip to main content

planus_buffer_inspection/
lib.rs

1use std::borrow::Cow;
2
3use planus_types::{
4    ast::{FloatType, IntegerType},
5    intermediate::{
6        DeclarationIndex, DeclarationKind, Declarations, FloatLiteral, IntegerLiteral, SimpleType,
7        StructField, Type, TypeKind, UnionVariant,
8    },
9};
10
11use crate::object_info::DeclarationInfo;
12
13pub mod children;
14pub mod object_info;
15pub mod object_mapping;
16
17pub type ByteIndex = u32;
18
19// TODO
20#[derive(Debug)]
21pub struct Error;
22
23type Result<T> = std::result::Result<T, Error>;
24
25#[derive(Copy, Clone)]
26pub struct InspectableFlatbuffer<'a> {
27    pub declarations: &'a Declarations,
28    pub buffer: &'a [u8],
29}
30
31impl<'a> InspectableFlatbuffer<'a> {
32    pub fn read_u8(&self, offset: ByteIndex) -> Result<u8> {
33        let offset = offset as usize;
34        Ok(self.buffer[offset])
35    }
36
37    pub fn read_u16(&self, offset: ByteIndex) -> Result<u16> {
38        let offset = offset as usize;
39        let slice: &[u8; 2] = self.buffer[offset..offset + 2].try_into().unwrap();
40        Ok(u16::from_le_bytes(*slice))
41    }
42
43    pub fn read_u32(&self, offset: ByteIndex) -> Result<u32> {
44        let offset = offset as usize;
45        let slice: &[u8; 4] = self.buffer[offset..offset + 4].try_into().unwrap();
46        Ok(u32::from_le_bytes(*slice))
47    }
48
49    pub fn read_u64(&self, offset: ByteIndex) -> Result<u64> {
50        let offset = offset as usize;
51        let slice: &[u8; 8] = self.buffer[offset..offset + 8].try_into().unwrap();
52        Ok(u64::from_le_bytes(*slice))
53    }
54
55    pub fn read_i8(&self, offset: ByteIndex) -> Result<i8> {
56        let offset = offset as usize;
57        Ok(self.buffer[offset] as i8)
58    }
59
60    pub fn read_i16(&self, offset: ByteIndex) -> Result<i16> {
61        let offset = offset as usize;
62        let slice: &[u8; 2] = self.buffer[offset..offset + 2].try_into().unwrap();
63        Ok(i16::from_le_bytes(*slice))
64    }
65
66    pub fn read_i32(&self, offset: ByteIndex) -> Result<i32> {
67        let offset = offset as usize;
68        let slice: &[u8; 4] = self.buffer[offset..offset + 4].try_into().unwrap();
69        Ok(i32::from_le_bytes(*slice))
70    }
71
72    pub fn read_i64(&self, offset: ByteIndex) -> Result<i64> {
73        let offset = offset as usize;
74        let slice: &[u8; 8] = self.buffer[offset..offset + 8].try_into().unwrap();
75        Ok(i64::from_le_bytes(*slice))
76    }
77
78    pub fn read_f32(&self, offset: ByteIndex) -> Result<f32> {
79        let offset = offset as usize;
80        let slice: &[u8; 4] = self.buffer[offset..offset + 4].try_into().unwrap();
81        Ok(f32::from_le_bytes(*slice))
82    }
83
84    pub fn read_f64(&self, offset: ByteIndex) -> Result<f64> {
85        let offset = offset as usize;
86        let slice: &[u8; 8] = self.buffer[offset..offset + 8].try_into().unwrap();
87        Ok(f64::from_le_bytes(*slice))
88    }
89
90    pub fn read_slice(&self, offset: ByteIndex, size: usize) -> Result<&'a [u8]> {
91        let offset = offset as usize;
92        Ok(&self.buffer[offset..offset + size])
93    }
94}
95
96#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
97pub enum Object<'a> {
98    /// 4 bytes of offset inside a table
99    Offset(OffsetObject<'a>),
100
101    /// 0 actual bytes, all bytes are sub-objects of u16 types
102    VTable(VTableObject),
103
104    /// 4 bytes of offset to a vtable. Fields are their own objects
105    Table(TableObject),
106
107    /// 0 bytes, actual bytes are in child objects
108    Struct(StructObject),
109
110    /// 1 byte of union tag
111    UnionTag(UnionTagObject),
112
113    /// 4 bytes of offset to the inner object
114    Union(UnionObject),
115
116    /// 4 bytes of offset to the tags vector
117    UnionVectorTags(UnionVectorTagsObject),
118
119    /// 4 bytes of offset to the values vector
120    UnionVectorValues(UnionVectorValuesObject),
121
122    /// 1, 2, 4 or 8 bytes of enum tag
123    Enum(EnumObject),
124
125    /// 4 bytes length field. The actual elements are their own values
126    Vector(VectorObject<'a>),
127
128    /// 0 bytes, actual elements are their own values
129    Array(ArrayObject<'a>),
130
131    /// 1, 2, 4 or 8 bytes of integer data
132    Integer(IntegerObject),
133
134    /// 4 or 8 bytes of float data
135    Float(FloatObject),
136
137    /// 1 byte of bool data
138    Bool(BoolObject),
139
140    /// 4+n bytes of length and strings
141    String(StringObject),
142
143    /// Unknown value
144    Unknown(ByteIndex),
145}
146
147impl Object<'_> {
148    pub fn offset(&self) -> ByteIndex {
149        match self {
150            Object::Offset(inner) => inner.offset,
151            Object::VTable(inner) => inner.offset,
152            Object::Table(inner) => inner.offset,
153            Object::Struct(inner) => inner.offset,
154            Object::UnionTag(inner) => inner.offset,
155            Object::Union(inner) => inner.offset,
156            Object::Enum(inner) => inner.offset,
157            Object::Vector(inner) => inner.offset,
158            Object::Array(inner) => inner.offset,
159            Object::Integer(inner) => inner.offset,
160            Object::Float(inner) => inner.offset,
161            Object::Bool(inner) => inner.offset,
162            Object::String(inner) => inner.offset,
163            Object::UnionVectorTags(inner) => inner.tags_offset,
164            Object::UnionVectorValues(inner) => inner.values_offset,
165            Object::Unknown(offset) => *offset,
166        }
167    }
168
169    pub fn have_braces(&self) -> bool {
170        match self {
171            Object::Offset(_) => false,
172            Object::VTable(_) => true,
173            Object::Table(_) => true,
174            Object::Struct(_) => true,
175            Object::UnionTag(_) => false,
176            Object::Union(_) => false,
177            Object::Enum(_) => false,
178            Object::Vector(_) => true,
179            Object::Array(_) => true,
180            Object::Integer(_) => false,
181            Object::Float(_) => false,
182            Object::Bool(_) => false,
183            Object::String(_) => false,
184            Object::UnionVectorTags(_) => true,
185            Object::UnionVectorValues(_) => true,
186            Object::Unknown(_) => false,
187        }
188    }
189
190    pub fn type_name(&self, declarations: &Declarations) -> Cow<'static, str> {
191        match self {
192            Object::Offset(inner) => inner.type_name(declarations),
193            Object::VTable(inner) => Cow::Owned(inner.type_name(declarations)),
194            Object::Table(inner) => Cow::Owned(inner.type_name(declarations)),
195            Object::Struct(inner) => Cow::Owned(inner.type_name(declarations)),
196            Object::UnionTag(inner) => Cow::Owned(inner.type_name(declarations)),
197            Object::Union(inner) => Cow::Owned(inner.type_name(declarations)),
198            Object::Enum(inner) => Cow::Owned(inner.type_name(declarations)),
199            Object::Vector(inner) => Cow::Owned(inner.type_name(declarations)),
200            Object::Array(inner) => Cow::Owned(inner.type_name(declarations)),
201            Object::Integer(inner) => Cow::Borrowed(inner.type_.flatbuffer_name()),
202            Object::Float(inner) => Cow::Borrowed(inner.type_.flatbuffer_name()),
203            Object::Bool(_) => Cow::Borrowed("bool"),
204            Object::String(_) => Cow::Borrowed("string"),
205            Object::UnionVectorTags(inner) => Cow::Owned(inner.type_name(declarations)),
206            Object::UnionVectorValues(inner) => Cow::Owned(inner.type_name(declarations)),
207            Object::Unknown(_) => Cow::Borrowed("?"),
208        }
209    }
210}
211
212#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
213pub struct OffsetObject<'a> {
214    pub offset: ByteIndex,
215    pub kind: OffsetObjectKind<'a>,
216}
217
218#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
219pub enum OffsetObjectKind<'a> {
220    VTable(DeclarationIndex),
221    Table(DeclarationIndex),
222    Vector(&'a Type),
223    UnionVectorTags {
224        declaration: DeclarationIndex,
225    },
226    UnionVector {
227        declaration: DeclarationIndex,
228        tags_offset: Option<ByteIndex>,
229    },
230    String,
231    Unknown,
232}
233
234#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
235pub struct VTableObject {
236    pub offset: ByteIndex,
237    pub declaration: DeclarationIndex,
238}
239
240#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
241pub struct TableOffsetObject {
242    pub offset: ByteIndex,
243    pub declaration: DeclarationIndex,
244}
245
246#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
247pub struct TableObject {
248    pub offset: ByteIndex,
249    pub declaration: DeclarationIndex,
250}
251
252#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
253pub struct StructObject {
254    pub offset: ByteIndex,
255    pub declaration: DeclarationIndex,
256}
257
258#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
259pub struct UnionTagObject {
260    pub offset: ByteIndex,
261    pub declaration: DeclarationIndex,
262}
263
264impl UnionTagObject {
265    fn type_name(&self, declarations: &Declarations) -> String {
266        format!(
267            "union tag {}",
268            declarations.get_declaration(self.declaration).0
269        )
270    }
271
272    pub fn tag_value(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u8> {
273        buffer.read_u8(self.offset)
274    }
275
276    pub fn tag_variant<'a>(
277        &self,
278        buffer: &InspectableFlatbuffer<'a>,
279    ) -> Result<Option<(&'a str, &'a UnionVariant)>> {
280        let decl = self.resolve_declaration(buffer);
281        if let Some((k, v)) = decl
282            .variants
283            .get_index(self.tag_value(buffer)? as usize - 1)
284        {
285            Ok(Some((k, v)))
286        } else {
287            Ok(None)
288        }
289    }
290}
291
292#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
293pub struct UnionObject {
294    pub tag: u8,
295    pub offset: ByteIndex,
296    pub declaration: DeclarationIndex,
297}
298
299#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
300pub struct EnumObject {
301    pub offset: ByteIndex,
302    pub declaration: DeclarationIndex,
303}
304
305#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
306pub struct VectorObject<'a> {
307    pub offset: ByteIndex,
308    pub type_: &'a Type,
309}
310
311#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
312pub struct UnionVectorTagsObject {
313    tags_offset: ByteIndex,
314    declaration: DeclarationIndex,
315}
316
317#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
318pub struct UnionVectorValuesObject {
319    tags_offset: Option<ByteIndex>,
320    values_offset: ByteIndex,
321    declaration: DeclarationIndex,
322}
323
324#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
325pub struct ArrayObject<'a> {
326    pub offset: ByteIndex,
327    pub type_: &'a Type,
328    pub size: u32,
329}
330
331impl ArrayObject<'_> {
332    pub fn type_name(&self, declarations: &Declarations) -> String {
333        format!(
334            "[{}; {}]",
335            declarations.format_type_kind(&self.type_.kind),
336            self.size
337        )
338    }
339}
340
341#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
342pub struct IntegerObject {
343    pub offset: ByteIndex,
344    pub type_: IntegerType,
345}
346
347#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
348pub struct FloatObject {
349    pub offset: ByteIndex,
350    pub type_: FloatType,
351}
352
353#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
354pub struct BoolObject {
355    pub offset: ByteIndex,
356}
357
358#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
359pub struct StringObject {
360    pub offset: ByteIndex,
361}
362
363impl<'a> OffsetObject<'a> {
364    pub fn get_byte_index(&self, buffer: &InspectableFlatbuffer<'a>) -> Result<ByteIndex> {
365        let res = if matches!(self.kind, OffsetObjectKind::VTable(_)) {
366            self.offset
367                .checked_add_signed(-buffer.read_i32(self.offset)?)
368                .ok_or(Error)?
369        } else {
370            self.offset + buffer.read_u32(self.offset)?
371        };
372        Ok(res)
373    }
374
375    pub fn follow_offset(&self, buffer: &InspectableFlatbuffer<'a>) -> Result<Object<'a>> {
376        let offset = self.get_byte_index(buffer)?;
377        match self.kind {
378            OffsetObjectKind::VTable(declaration) => Ok(Object::VTable(VTableObject {
379                declaration,
380                offset,
381            })),
382            OffsetObjectKind::Table(declaration) => Ok(Object::Table(TableObject {
383                offset,
384                declaration,
385            })),
386            OffsetObjectKind::Vector(type_) => Ok(Object::Vector(VectorObject { offset, type_ })),
387            OffsetObjectKind::UnionVector {
388                declaration,
389                tags_offset,
390            } => Ok(Object::UnionVectorValues(UnionVectorValuesObject {
391                tags_offset: if let Some(tags_offset) = tags_offset {
392                    Some(tags_offset + buffer.read_u32(tags_offset)?)
393                } else {
394                    None
395                },
396                values_offset: offset,
397                declaration,
398            })),
399
400            OffsetObjectKind::UnionVectorTags { declaration } => {
401                Ok(Object::UnionVectorTags(UnionVectorTagsObject {
402                    tags_offset: offset,
403                    declaration,
404                }))
405            }
406            OffsetObjectKind::String => Ok(Object::String(StringObject { offset })),
407            OffsetObjectKind::Unknown => Ok(Object::Unknown(offset)),
408        }
409    }
410
411    fn type_name(&self, declarations: &Declarations) -> Cow<'static, str> {
412        match self.kind {
413            OffsetObjectKind::VTable(index) => {
414                Cow::Owned(format!("&vtable {}", declarations.get_declaration(index).0))
415            }
416            OffsetObjectKind::Table(index) => {
417                Cow::Owned(format!("&table {}", declarations.get_declaration(index).0))
418            }
419            OffsetObjectKind::Vector(type_) => {
420                Cow::Owned(format!("&[{}]", declarations.format_type_kind(&type_.kind)))
421            }
422            OffsetObjectKind::UnionVector { declaration, .. } => Cow::Owned(format!(
423                "&[{}]",
424                declarations.get_declaration(declaration).0
425            )),
426
427            OffsetObjectKind::UnionVectorTags { declaration, .. } => Cow::Owned(format!(
428                "&[{}] (tags)",
429                declarations.get_declaration(declaration).0
430            )),
431            OffsetObjectKind::String => Cow::Borrowed("&string"),
432            OffsetObjectKind::Unknown => Cow::Borrowed("&?"),
433        }
434    }
435}
436
437impl VTableObject {
438    pub fn get_vtable_size(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u16> {
439        buffer.read_u16(self.offset)
440    }
441
442    pub fn get_table_size(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u16> {
443        buffer.read_u16(self.offset + 2)
444    }
445
446    pub fn get_offset(&self, i: u32, buffer: &InspectableFlatbuffer<'_>) -> Result<Option<u16>> {
447        let value = buffer.read_u16(self.offset + 4 + 2 * i)?;
448        let value = (value != 0).then_some(value);
449        Ok(value)
450    }
451
452    pub fn get_offsets<'a>(
453        &self,
454        buffer: &InspectableFlatbuffer<'a>,
455    ) -> Result<impl 'a + ExactSizeIterator<Item = u16> + DoubleEndedIterator> {
456        let size = self.get_vtable_size(buffer)?;
457        let slice: &[u8] = buffer.read_slice(self.offset, size as usize)?;
458        Ok(slice[4..].chunks_exact(2).map(move |chunk| {
459            let slice: &[u8; 2] = chunk.try_into().unwrap();
460            u16::from_le_bytes(*slice)
461        }))
462    }
463
464    fn type_name(&self, declarations: &Declarations) -> String {
465        format!(
466            "vtable for {}",
467            declarations.get_declaration(self.declaration).0
468        )
469    }
470}
471
472impl TableObject {
473    pub fn get_vtable(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<VTableObject> {
474        let vtable_offset = self
475            .offset
476            .checked_add_signed(-buffer.read_i32(self.offset)?)
477            .unwrap();
478
479        Ok(VTableObject {
480            declaration: self.declaration,
481            offset: vtable_offset,
482        })
483    }
484
485    pub fn get_field<'a>(
486        &self,
487        buffer: &InspectableFlatbuffer<'a>,
488        field_index: u32,
489    ) -> Result<Option<Object<'a>>> {
490        let decl = self.resolve_declaration(buffer);
491        let Some(object_offset) = self.get_vtable(buffer)?.get_offset(field_index, buffer)? else {
492            return Ok(None);
493        };
494
495        let offset = self.offset + object_offset as u32;
496        let (_field_name, field_decl, is_union_tag) =
497            decl.get_field_for_vtable_index(field_index).unwrap();
498        let object = match field_decl.type_.kind {
499            TypeKind::Table(declaration) => Object::Offset(OffsetObject {
500                offset,
501                kind: OffsetObjectKind::Table(declaration),
502            }),
503            TypeKind::Union(declaration) if is_union_tag => Object::UnionTag(UnionTagObject {
504                offset,
505                declaration,
506            }),
507            TypeKind::Union(declaration) => {
508                let Some(tag_offset) = self
509                    .get_vtable(buffer)?
510                    .get_offset(field_index - 1, buffer)?
511                else {
512                    return Ok(None);
513                };
514
515                let tag_offset = self.offset + tag_offset as u32;
516                if let Ok(tag) = buffer.read_u8(tag_offset) {
517                    Object::Union(UnionObject {
518                        tag,
519                        offset,
520                        declaration,
521                    })
522                } else {
523                    return Ok(None);
524                }
525            }
526            TypeKind::Vector(ref type_) if is_union_tag => Object::Offset(OffsetObject {
527                offset,
528                kind: OffsetObjectKind::UnionVectorTags {
529                    declaration: if let TypeKind::Union(declaration) = &type_.kind {
530                        *declaration
531                    } else {
532                        return Ok(None);
533                    },
534                },
535            }),
536            TypeKind::Vector(ref type_) if matches!(type_.kind, TypeKind::Union(_)) => {
537                let tags = self
538                    .get_vtable(buffer)?
539                    .get_offset(field_index - 1, buffer)?
540                    .map(|tag_offset| self.offset + tag_offset as u32);
541
542                Object::Offset(OffsetObject {
543                    offset,
544                    kind: OffsetObjectKind::UnionVector {
545                        declaration: if let TypeKind::Union(declaration) = &type_.kind {
546                            *declaration
547                        } else {
548                            return Ok(None);
549                        },
550                        tags_offset: tags,
551                    },
552                })
553            }
554            TypeKind::Vector(ref type_) => Object::Offset(OffsetObject {
555                offset,
556                kind: OffsetObjectKind::Vector(type_),
557            }),
558            TypeKind::Array(ref _type_, _size) => todo!(),
559            TypeKind::SimpleType(type_) => match type_ {
560                SimpleType::Struct(declaration) => Object::Struct(StructObject {
561                    offset,
562                    declaration,
563                }),
564                SimpleType::Enum(declaration) => Object::Enum(EnumObject {
565                    offset,
566                    declaration,
567                }),
568                SimpleType::Bool => Object::Bool(BoolObject { offset }),
569                SimpleType::Integer(type_) => Object::Integer(IntegerObject { offset, type_ }),
570                SimpleType::Float(type_) => Object::Float(FloatObject { offset, type_ }),
571            },
572            TypeKind::String => Object::Offset(OffsetObject {
573                offset,
574                kind: OffsetObjectKind::String,
575            }),
576        };
577        Ok(Some(object))
578    }
579
580    fn type_name(&self, declarations: &Declarations) -> String {
581        format!("table {}", declarations.get_declaration(self.declaration).0)
582    }
583}
584
585impl StructObject {
586    pub fn get_field_info<'a>(
587        &self,
588        buffer: &InspectableFlatbuffer<'a>,
589        field_index: usize,
590    ) -> Option<(&'a str, &'a StructField)> {
591        let decl = self.resolve_declaration(buffer);
592        let (field_name, field) = decl.fields.get_index(field_index)?;
593        Some((field_name.as_str(), field))
594    }
595
596    pub fn get_field<'a>(
597        &self,
598        buffer: &InspectableFlatbuffer<'a>,
599        field_index: usize,
600    ) -> Result<Object<'a>> {
601        let Some((_field_name, field)) = self.get_field_info(buffer, field_index) else {
602            return Err(Error);
603        };
604
605        let offset = self.offset + field.offset;
606        let object = match field.type_ {
607            SimpleType::Struct(declaration) => Object::Struct(StructObject {
608                offset,
609                declaration,
610            }),
611            SimpleType::Enum(declaration) => Object::Enum(EnumObject {
612                offset,
613                declaration,
614            }),
615            SimpleType::Bool => Object::Bool(BoolObject { offset }),
616            SimpleType::Integer(type_) => Object::Integer(IntegerObject { offset, type_ }),
617            SimpleType::Float(type_) => Object::Float(FloatObject { offset, type_ }),
618        };
619        Ok(object)
620    }
621
622    fn type_name(&self, declarations: &Declarations) -> String {
623        format!(
624            "struct {}",
625            declarations.get_declaration(self.declaration).0
626        )
627    }
628}
629
630impl UnionObject {
631    pub fn inner_offset<'a>(
632        &self,
633        buffer: &InspectableFlatbuffer<'a>,
634    ) -> Result<Option<OffsetObject<'a>>> {
635        if let Some((_name, variant)) = self.tag_variant(buffer)? {
636            Ok(Some(OffsetObject {
637                offset: self.offset,
638                kind: match &variant.type_.kind {
639                    TypeKind::Table(index) => OffsetObjectKind::Table(*index),
640                    TypeKind::Vector(type_) => OffsetObjectKind::Vector(type_),
641                    TypeKind::String => OffsetObjectKind::String,
642                    TypeKind::Array(_, _) | TypeKind::SimpleType(_) | TypeKind::Union(_) => {
643                        panic!("Inconsistent declarations")
644                    }
645                },
646            }))
647        } else {
648            Ok(None)
649        }
650    }
651
652    fn type_name(&self, declarations: &Declarations) -> String {
653        format!(
654            "&union {}",
655            declarations.get_declaration(self.declaration).0
656        )
657    }
658
659    pub fn tag_variant<'a>(
660        &self,
661        buffer: &InspectableFlatbuffer<'a>,
662    ) -> Result<Option<(&'a str, &'a UnionVariant)>> {
663        let decl = self.resolve_declaration(buffer);
664        if let Some((k, v)) = decl.variants.get_index(self.tag as usize - 1) {
665            Ok(Some((k, v)))
666        } else {
667            Ok(None)
668        }
669    }
670}
671
672impl EnumObject {
673    pub fn tag(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<IntegerObject> {
674        let (_, decl) = buffer.declarations.get_declaration(self.declaration);
675
676        if let DeclarationKind::Enum(e) = &decl.kind {
677            Ok(IntegerObject {
678                offset: self.offset,
679                type_: e.type_,
680            })
681        } else {
682            Err(Error)
683        }
684    }
685
686    pub fn read(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u64> {
687        let tag = self.tag(buffer)?;
688        let val = tag.read(buffer)?;
689        Ok(val.to_u64())
690    }
691
692    fn type_name(&self, declarations: &Declarations) -> String {
693        format!("enum {}", declarations.get_declaration(self.declaration).0)
694    }
695}
696
697impl StringObject {
698    pub fn len(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u32> {
699        buffer.read_u32(self.offset)
700    }
701
702    pub fn bytes<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> Result<&'a [u8]> {
703        let offset = self.offset as usize;
704        Ok(&buffer.buffer[offset + 4..offset + 4 + self.len(buffer)? as usize])
705    }
706}
707
708impl BoolObject {
709    pub fn read(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<bool> {
710        Ok(buffer.buffer[self.offset as usize] != 0)
711    }
712}
713
714impl FloatObject {
715    pub fn read(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<FloatLiteral> {
716        match self.type_ {
717            FloatType::F32 => Ok(FloatLiteral::F32(buffer.read_f32(self.offset)?)),
718            FloatType::F64 => Ok(FloatLiteral::F64(buffer.read_f64(self.offset)?)),
719        }
720    }
721}
722
723impl IntegerObject {
724    pub fn read(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<IntegerLiteral> {
725        let literal = match self.type_ {
726            IntegerType::U8 => IntegerLiteral::U8(buffer.read_u8(self.offset)?),
727            IntegerType::U16 => IntegerLiteral::U16(buffer.read_u16(self.offset)?),
728            IntegerType::U32 => IntegerLiteral::U32(buffer.read_u32(self.offset)?),
729            IntegerType::U64 => IntegerLiteral::U64(buffer.read_u64(self.offset)?),
730            IntegerType::I8 => IntegerLiteral::I8(buffer.read_i8(self.offset)?),
731            IntegerType::I16 => IntegerLiteral::I16(buffer.read_i16(self.offset)?),
732            IntegerType::I32 => IntegerLiteral::I32(buffer.read_i32(self.offset)?),
733            IntegerType::I64 => IntegerLiteral::I64(buffer.read_i64(self.offset)?),
734        };
735        Ok(literal)
736    }
737}
738
739impl<'a> VectorObject<'a> {
740    pub fn len(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u32> {
741        buffer.read_u32(self.offset)
742    }
743
744    pub fn read(
745        &self,
746        index: u32,
747        buffer: &InspectableFlatbuffer<'a>,
748    ) -> Result<Option<Object<'a>>> {
749        if index >= self.len(buffer)? {
750            return Ok(None);
751        }
752
753        let offset = self.offset + 4;
754        let object = match &self.type_.kind {
755            TypeKind::Union(_) => return Ok(None),
756            TypeKind::Array(_, _) => return Ok(None),
757            TypeKind::Table(declaration_index) => Object::Offset(OffsetObject {
758                offset: offset + index * 4,
759                kind: OffsetObjectKind::Table(*declaration_index),
760            }),
761            TypeKind::Vector(type_) => Object::Offset(OffsetObject {
762                offset: offset + index * 4,
763                kind: OffsetObjectKind::Vector(type_),
764            }),
765
766            TypeKind::String => Object::Offset(OffsetObject {
767                offset: offset + index * 4,
768                kind: OffsetObjectKind::String,
769            }),
770
771            TypeKind::SimpleType(type_) => match type_ {
772                SimpleType::Struct(declaration_index) => {
773                    if let DeclarationKind::Struct(decl) = &buffer
774                        .declarations
775                        .get_declaration(*declaration_index)
776                        .1
777                        .kind
778                    {
779                        Object::Struct(StructObject {
780                            offset: offset + index * decl.size,
781                            declaration: *declaration_index,
782                        })
783                    } else {
784                        panic!("Inconsistent declarations");
785                    }
786                }
787                SimpleType::Enum(declaration_index) => {
788                    if let DeclarationKind::Enum(decl) = &buffer
789                        .declarations
790                        .get_declaration(*declaration_index)
791                        .1
792                        .kind
793                    {
794                        Object::Enum(EnumObject {
795                            offset: offset + index * decl.type_.byte_size(),
796                            declaration: *declaration_index,
797                        })
798                    } else {
799                        panic!("Inconsistent declarations");
800                    }
801                }
802                SimpleType::Bool => Object::Bool(BoolObject {
803                    offset: offset + index,
804                }),
805                SimpleType::Integer(type_) => Object::Integer(IntegerObject {
806                    offset: offset + index * type_.byte_size(),
807                    type_: *type_,
808                }),
809                SimpleType::Float(type_) => Object::Float(FloatObject {
810                    offset: offset + index * type_.byte_size(),
811                    type_: *type_,
812                }),
813            },
814        };
815        Ok(Some(object))
816    }
817
818    fn type_name(&self, declarations: &Declarations) -> String {
819        format!("[{}]", declarations.format_type_kind(&self.type_.kind))
820    }
821}
822
823impl UnionVectorTagsObject {
824    pub fn len(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u32> {
825        buffer.read_u32(self.tags_offset)
826    }
827
828    fn type_name(&self, declarations: &Declarations) -> String {
829        format!(
830            "[{}] (tags)",
831            declarations.get_declaration(self.declaration).0
832        )
833    }
834}
835
836impl UnionVectorValuesObject {
837    pub fn len(&self, buffer: &InspectableFlatbuffer<'_>) -> Result<u32> {
838        buffer.read_u32(self.values_offset)
839    }
840
841    fn type_name(&self, declarations: &Declarations) -> String {
842        format!("[{}]", declarations.get_declaration(self.declaration).0)
843    }
844}