Skip to main content

planus_buffer_inspection/
object_info.rs

1use planus_types::intermediate::{
2    AbsolutePath, DeclarationIndex, DeclarationKind, Enum, SimpleType, Struct, Table, TypeKind,
3    Union,
4};
5
6use crate::{
7    ArrayObject, BoolObject, EnumObject, FloatObject, InspectableFlatbuffer, IntegerObject, Object,
8    OffsetObject, StringObject, StructObject, TableObject, UnionObject, UnionTagObject,
9    UnionVectorTagsObject, UnionVectorValuesObject, VTableObject, VectorObject,
10};
11
12pub trait DeclarationInfo {
13    type Declaration;
14    const KIND: &'static str;
15
16    fn declaration_index(&self) -> DeclarationIndex;
17    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Self::Declaration;
18    fn resolve_path<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a AbsolutePath {
19        buffer
20            .declarations
21            .get_declaration(self.declaration_index())
22            .0
23    }
24}
25
26macro_rules! impl_object_name {
27    ($typ:ty) => {
28        impl<'a> ObjectName<'a> for $typ {
29            fn print_object(&self, buffer: &InspectableFlatbuffer<'_>) -> String {
30                format!("{}", self.resolve_path(buffer).0.last().unwrap())
31            }
32        }
33    };
34}
35
36pub trait ObjectName<'a> {
37    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String;
38}
39
40impl DeclarationInfo for TableObject {
41    type Declaration = Table;
42    const KIND: &'static str = "table";
43
44    fn declaration_index(&self) -> DeclarationIndex {
45        self.declaration
46    }
47
48    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Table {
49        if let DeclarationKind::Table(decl) =
50            &buffer.declarations.get_declaration(self.declaration).1.kind
51        {
52            decl
53        } else {
54            panic!("Inconsistent declarations");
55        }
56    }
57}
58
59impl DeclarationInfo for StructObject {
60    type Declaration = Struct;
61    const KIND: &'static str = "struct";
62
63    fn declaration_index(&self) -> DeclarationIndex {
64        self.declaration
65    }
66
67    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Struct {
68        if let DeclarationKind::Struct(decl) =
69            &buffer.declarations.get_declaration(self.declaration).1.kind
70        {
71            decl
72        } else {
73            panic!("Inconsistent declarations");
74        }
75    }
76}
77
78impl DeclarationInfo for UnionTagObject {
79    type Declaration = Union;
80    const KIND: &'static str = "union_key";
81
82    fn declaration_index(&self) -> DeclarationIndex {
83        self.declaration
84    }
85
86    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Union {
87        if let DeclarationKind::Union(decl) =
88            &buffer.declarations.get_declaration(self.declaration).1.kind
89        {
90            decl
91        } else {
92            panic!("Inconsistent declarations");
93        }
94    }
95}
96
97impl DeclarationInfo for UnionObject {
98    type Declaration = Union;
99    const KIND: &'static str = "union";
100
101    fn declaration_index(&self) -> DeclarationIndex {
102        self.declaration
103    }
104
105    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Union {
106        if let DeclarationKind::Union(decl) =
107            &buffer.declarations.get_declaration(self.declaration).1.kind
108        {
109            decl
110        } else {
111            panic!("Inconsistent declarations");
112        }
113    }
114}
115
116impl DeclarationInfo for EnumObject {
117    type Declaration = Enum;
118    const KIND: &'static str = "enum";
119
120    fn declaration_index(&self) -> DeclarationIndex {
121        self.declaration
122    }
123
124    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Enum {
125        if let DeclarationKind::Enum(decl) =
126            &buffer.declarations.get_declaration(self.declaration).1.kind
127        {
128            decl
129        } else {
130            panic!("Inconsistent declarations");
131        }
132    }
133}
134
135impl DeclarationInfo for VTableObject {
136    type Declaration = Table;
137    const KIND: &'static str = "vtable";
138
139    fn declaration_index(&self) -> DeclarationIndex {
140        self.declaration
141    }
142
143    fn resolve_declaration<'a>(&self, buffer: &InspectableFlatbuffer<'a>) -> &'a Table {
144        if let DeclarationKind::Table(decl) =
145            &buffer.declarations.get_declaration(self.declaration).1.kind
146        {
147            decl
148        } else {
149            panic!("Inconsistent declarations");
150        }
151    }
152}
153
154impl<'a> ObjectName<'a> for VTableObject {
155    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
156        let path = buffer.declarations.get_declaration(self.declaration).0;
157        let path = path.0.last().unwrap();
158        format!("vtable {path}")
159    }
160}
161
162impl<'a> ObjectName<'a> for OffsetObject<'a> {
163    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
164        self.follow_offset(buffer).map_or_else(
165            |_| "invalid offset".to_string(),
166            |inner| inner.print_object(buffer),
167        )
168    }
169}
170
171impl<'a> ObjectName<'a> for VectorObject<'a> {
172    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
173        let len = if let Ok(len) = self.len(buffer) {
174            len.to_string()
175        } else {
176            "?".to_string()
177        };
178
179        if let TypeKind::Table(declaration_index)
180        | TypeKind::Union(declaration_index)
181        | TypeKind::SimpleType(SimpleType::Enum(declaration_index))
182        | TypeKind::SimpleType(SimpleType::Struct(declaration_index)) = self.type_.kind
183        {
184            let (path, _) = buffer.declarations.get_declaration(declaration_index);
185            let path = path.0.last().unwrap();
186            format!("[{path}; {len}]",)
187        } else {
188            format!("[{:?}; {len}]", self.type_.kind)
189        }
190    }
191}
192
193impl<'a> ObjectName<'a> for UnionVectorTagsObject {
194    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
195        let len = if let Ok(len) = self.len(buffer) {
196            len.to_string()
197        } else {
198            "?".to_string()
199        };
200
201        let (path, _) = buffer.declarations.get_declaration(self.declaration);
202        let path = path.0.last().unwrap();
203        format!("[{path}; {len}]",)
204    }
205}
206
207impl<'a> ObjectName<'a> for UnionVectorValuesObject {
208    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
209        let len = if let Ok(len) = self.len(buffer) {
210            len.to_string()
211        } else {
212            "?".to_string()
213        };
214
215        let (path, _) = buffer.declarations.get_declaration(self.declaration);
216        let path = path.0.last().unwrap();
217        format!("[{path}; {len}]",)
218    }
219}
220
221impl<'a> ObjectName<'a> for ArrayObject<'a> {
222    fn print_object(&self, _buffer: &InspectableFlatbuffer<'a>) -> String {
223        "ARRAY".to_string() // TODO
224    }
225}
226
227impl<'a> ObjectName<'a> for IntegerObject {
228    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
229        format!("{}", self.read(buffer).unwrap())
230    }
231}
232
233impl<'a> ObjectName<'a> for FloatObject {
234    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
235        format!("{}", self.read(buffer).unwrap())
236    }
237}
238
239impl<'a> ObjectName<'a> for BoolObject {
240    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
241        format!("{}", self.read(buffer).unwrap())
242    }
243}
244
245impl<'a> ObjectName<'a> for StringObject {
246    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
247        format!(
248            "{:?} (len={})",
249            String::from_utf8_lossy(self.bytes(buffer).unwrap()),
250            self.len(buffer).unwrap()
251        )
252    }
253}
254
255impl<'a> ObjectName<'a> for EnumObject {
256    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
257        let tag = self.tag(buffer).unwrap();
258        let (path, decl) = buffer
259            .declarations
260            .get_declaration(self.declaration_index());
261        if let DeclarationKind::Enum(e) = &decl.kind {
262            let tag = tag.read(buffer).unwrap();
263            let path = path.0.last().unwrap();
264            if let Some(variant) = e.variants.get(&tag) {
265                format!("{path}::{}", variant.name)
266            } else {
267                format!("{path}::UnknownTag({tag})")
268            }
269        } else {
270            panic!("Inconsistent declarations");
271        }
272    }
273}
274
275impl_object_name!(StructObject);
276impl_object_name!(TableObject);
277
278impl<'a> ObjectName<'a> for UnionTagObject {
279    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
280        let path = buffer.declarations.get_declaration(self.declaration).0;
281        let path = path.0.last().unwrap();
282        match self.tag_variant(buffer) {
283            Ok(Some((variant_name, _variant))) => {
284                format!("{path}::{variant_name}")
285            }
286            Ok(None) => {
287                format!(
288                    "{path}::UnknownVariant({})",
289                    self.tag_value(buffer).unwrap()
290                )
291            }
292            Err(_) => {
293                format!("{path}::ERROR")
294            }
295        }
296    }
297}
298
299impl<'a> ObjectName<'a> for UnionObject {
300    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
301        let path = buffer.declarations.get_declaration(self.declaration).0;
302        let path = path.0.last().unwrap();
303        match self.tag_variant(buffer) {
304            Ok(Some((variant_name, _variant))) => {
305                format!("{path}::{variant_name}")
306            }
307            Ok(None) => {
308                format!("{path}::UnknownVariant({})", self.tag)
309            }
310            Err(_) => {
311                format!("{path}::ERROR")
312            }
313        }
314    }
315}
316
317impl<'a> ObjectName<'a> for Object<'a> {
318    fn print_object(&self, buffer: &InspectableFlatbuffer<'a>) -> String {
319        match self {
320            Object::Offset(obj) => obj.print_object(buffer),
321            Object::VTable(obj) => obj.print_object(buffer),
322            Object::Table(obj) => obj.print_object(buffer),
323            Object::Struct(obj) => obj.print_object(buffer),
324            Object::UnionTag(obj) => obj.print_object(buffer),
325            Object::Union(obj) => obj.print_object(buffer),
326            Object::Enum(obj) => obj.print_object(buffer),
327            Object::Vector(obj) => obj.print_object(buffer),
328            Object::Array(obj) => obj.print_object(buffer),
329            Object::Integer(obj) => obj.print_object(buffer),
330            Object::Float(obj) => obj.print_object(buffer),
331            Object::Bool(obj) => obj.print_object(buffer),
332            Object::String(obj) => obj.print_object(buffer),
333            Object::UnionVectorTags(obj) => obj.print_object(buffer),
334            Object::UnionVectorValues(obj) => obj.print_object(buffer),
335            Object::Unknown(_) => "?".to_string(),
336        }
337    }
338}