1use std::borrow::Cow;
2
3use planus_types::{ast::IntegerType, intermediate::TypeKind};
4
5use crate::{
6 object_info::DeclarationInfo, ArrayObject, BoolObject, ByteIndex, EnumObject, FloatObject,
7 InspectableFlatbuffer, IntegerObject, Object, OffsetObject, StringObject, StructObject,
8 TableObject, UnionObject, UnionTagObject, UnionVectorTagsObject, UnionVectorValuesObject,
9 VTableObject, VectorObject,
10};
11
12pub trait Children<'a> {
13 fn children(
14 &self,
15 buffer: &InspectableFlatbuffer<'a>,
16 callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
17 );
18}
19
20pub trait Byterange {
21 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex);
22}
23
24impl<'a> Children<'a> for Object<'a> {
25 fn children(
26 &self,
27 buffer: &InspectableFlatbuffer<'a>,
28 callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
29 ) {
30 match self {
31 Object::Offset(_) => (),
32 Object::VTable(obj) => obj.children(buffer, callback),
33 Object::Table(obj) => obj.children(buffer, callback),
34 Object::Struct(obj) => obj.children(buffer, callback),
35 Object::UnionTag(obj) => obj.children(buffer, callback),
36 Object::Union(obj) => obj.children(buffer, callback),
37 Object::Enum(obj) => obj.children(buffer, callback),
38 Object::Vector(obj) => obj.children(buffer, callback),
39 Object::Array(obj) => obj.children(buffer, callback),
40 Object::Integer(obj) => obj.children(buffer, callback),
41 Object::Float(obj) => obj.children(buffer, callback),
42 Object::Bool(obj) => obj.children(buffer, callback),
43 Object::String(obj) => obj.children(buffer, callback),
44 Object::UnionVectorTags(obj) => obj.children(buffer, callback),
45 Object::UnionVectorValues(obj) => obj.children(buffer, callback),
46 Object::Unknown(_) => (),
47 }
48 }
49}
50
51impl<'a> Children<'a> for VTableObject {
52 fn children(
53 &self,
54 buffer: &InspectableFlatbuffer<'a>,
55 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
56 ) {
57 let vtable_size = self.get_vtable_size(buffer).unwrap();
58 let decl = self.resolve_declaration(buffer);
59
60 for (i, offset) in (self.offset..self.offset + vtable_size as u32)
61 .step_by(2)
62 .enumerate()
63 {
64 let object = Object::Integer(IntegerObject {
65 offset,
66 type_: IntegerType::U16,
67 });
68 match i {
69 0 => callback(Some(Cow::Borrowed("#vtable_size")), object),
70 1 => callback(Some(Cow::Borrowed("#table_size")), object),
71 n => {
72 let n = n - 2;
73 if let Some((k, v)) = decl.fields.get_index(n) {
74 if matches!(v.type_.kind, TypeKind::Union(_)) {
75 callback(Some(Cow::Owned(format!("offset[union_tag[{k}]]"))), object)
76 } else {
77 callback(Some(Cow::Owned(format!("offset[{k}]"))), object)
78 }
79 } else if let Some((k, _v)) = decl
80 .fields
81 .get_index(n - 1)
82 .filter(|(_k, v)| matches!(v.type_.kind, TypeKind::Union(_)))
83 {
84 callback(Some(Cow::Owned(format!("offset[union[{k}]]"))), object)
85 } else {
86 callback(Some(Cow::Owned(format!("offset[{n}]"))), object)
87 }
88 }
89 }
90 }
91 }
92}
93
94impl<'a> Children<'a> for TableObject {
95 fn children(
96 &self,
97 buffer: &InspectableFlatbuffer<'a>,
98 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
99 ) {
100 callback(
101 Some(Cow::Borrowed("#vtable")),
102 Object::Offset(OffsetObject {
103 offset: self.offset,
104 kind: crate::OffsetObjectKind::VTable(self.declaration),
105 }),
106 );
107
108 let vtable = self.get_vtable(buffer).unwrap();
109 let decl = self.resolve_declaration(buffer);
110 for (i, offset) in vtable.get_offsets(buffer).unwrap().enumerate() {
111 if offset == 0 {
112 continue;
113 }
114 let (field_name, _field_decl, is_union_tag) =
115 decl.get_field_for_vtable_index(i as u32).unwrap();
116 let field_name = if is_union_tag {
117 Cow::Owned(format!("union_key[{field_name}]"))
118 } else {
119 Cow::Borrowed(field_name)
120 };
121 if let Some(field_value) = self.get_field(buffer, i as u32).unwrap() {
122 callback(Some(field_name), field_value);
123 }
124 }
125 }
126}
127
128impl<'a> Children<'a> for StructObject {
129 fn children(
130 &self,
131 buffer: &InspectableFlatbuffer<'a>,
132 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
133 ) {
134 let this = *self;
135 let buffer = *buffer;
136 let decl = self.resolve_declaration(&buffer);
137 for (i, field_name) in decl.fields.keys().enumerate() {
138 if let Ok(field) = this.get_field(&buffer, i) {
139 callback(Some(Cow::Borrowed(field_name.as_str())), field);
140 }
141 }
142 }
143}
144
145impl<'a> Children<'a> for UnionTagObject {
146 fn children(
147 &self,
148 _buffer: &InspectableFlatbuffer<'a>,
149 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
150 ) {
151 }
152}
153
154impl<'a> Children<'a> for UnionObject {
155 fn children(
156 &self,
157 buffer: &InspectableFlatbuffer<'a>,
158 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
159 ) {
160 match self.inner_offset(buffer) {
161 Ok(Some(inner_offset)) => callback(None, Object::Offset(inner_offset)),
162 Ok(None) => callback(
163 Some(Cow::Borrowed("unknown offset")),
164 Object::Integer(IntegerObject {
165 offset: self.offset,
166 type_: IntegerType::U32,
167 }),
168 ),
169 Err(_) => callback(
170 Some(Cow::Borrowed("error offset")),
171 Object::Integer(IntegerObject {
172 offset: self.offset,
173 type_: IntegerType::U32,
174 }),
175 ),
176 }
177 }
178}
179
180impl<'a> Children<'a> for EnumObject {
181 fn children(
182 &self,
183 _buffer: &InspectableFlatbuffer<'a>,
184 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
185 ) {
186 }
187}
188
189impl<'a> Children<'a> for VectorObject<'a> {
190 fn children(
191 &self,
192 buffer: &InspectableFlatbuffer<'a>,
193 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
194 ) {
195 callback(
196 Some(Cow::Borrowed("length")),
197 Object::Integer(IntegerObject {
198 offset: self.offset,
199 type_: IntegerType::U32,
200 }),
201 );
202
203 for i in 0..self.len(buffer).unwrap_or(0) {
204 if let Ok(Some(value)) = self.read(i, buffer) {
205 callback(Some(Cow::Owned(i.to_string())), value);
206 }
207 }
208 }
209}
210
211impl<'a> Children<'a> for ArrayObject<'a> {
212 fn children(
213 &self,
214 _buffer: &InspectableFlatbuffer<'a>,
215 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
216 ) {
217 }
218}
219
220impl<'a> Children<'a> for IntegerObject {
221 fn children(
222 &self,
223 _buffer: &InspectableFlatbuffer<'a>,
224 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
225 ) {
226 }
227}
228
229impl<'a> Children<'a> for FloatObject {
230 fn children(
231 &self,
232 _buffer: &InspectableFlatbuffer<'a>,
233 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
234 ) {
235 }
236}
237
238impl<'a> Children<'a> for BoolObject {
239 fn children(
240 &self,
241 _buffer: &InspectableFlatbuffer<'a>,
242 _callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
243 ) {
244 }
245}
246
247impl<'a> Children<'a> for StringObject {
248 fn children(
249 &self,
250 _buffer: &InspectableFlatbuffer<'a>,
251 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
252 ) {
253 callback(
254 Some(Cow::Borrowed("length")),
255 Object::Integer(IntegerObject {
256 offset: self.offset,
257 type_: IntegerType::U32,
258 }),
259 );
260 }
261}
262
263impl<'a> Children<'a> for UnionVectorTagsObject {
264 fn children(
265 &self,
266 buffer: &InspectableFlatbuffer<'a>,
267 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
268 ) {
269 let offset = self.tags_offset;
270 callback(
271 Some(Cow::Borrowed("length")),
272 Object::Integer(IntegerObject {
273 offset,
274 type_: IntegerType::U32,
275 }),
276 );
277
278 for i in 0..self.len(buffer).unwrap_or(0) {
279 let offset = offset + 4 + i;
280 let value = UnionTagObject {
281 offset,
282 declaration: self.declaration,
283 };
284 callback(Some(Cow::Owned(i.to_string())), Object::UnionTag(value));
285 }
286 }
287}
288
289impl<'a> Children<'a> for UnionVectorValuesObject {
290 fn children(
291 &self,
292 buffer: &InspectableFlatbuffer<'a>,
293 mut callback: impl FnMut(Option<Cow<'a, str>>, Object<'a>),
294 ) {
295 let offset = self.values_offset;
296 callback(
297 Some(Cow::Borrowed("length")),
298 Object::Integer(IntegerObject {
299 offset,
300 type_: IntegerType::U32,
301 }),
302 );
303
304 for i in 0..self.len(buffer).unwrap_or(0) {
305 let offset = offset + 4 + 4 * i;
306 let tag = self
307 .tags_offset
308 .and_then(|tag_offset| buffer.read_u8(tag_offset + 4 + i).ok());
309
310 if let Some(tag) = tag {
311 let value = UnionObject {
312 offset,
313 tag,
314 declaration: self.declaration,
315 };
316 callback(Some(Cow::Owned(i.to_string())), Object::Union(value));
317 } else {
318 callback(
319 Some(Cow::Owned(i.to_string())),
320 Object::Offset(OffsetObject {
321 offset,
322 kind: crate::OffsetObjectKind::Unknown,
323 }),
324 );
325 }
326 }
327 }
328}
329
330impl Byterange for Object<'_> {
331 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
332 match self {
333 Object::Offset(obj) => obj.byterange(buffer),
334 Object::VTable(obj) => obj.byterange(buffer),
335 Object::Table(obj) => obj.byterange(buffer),
336 Object::Struct(obj) => obj.byterange(buffer),
337 Object::UnionTag(obj) => obj.byterange(buffer),
338 Object::Union(obj) => obj.byterange(buffer),
339 Object::Enum(obj) => obj.byterange(buffer),
340 Object::Vector(obj) => obj.byterange(buffer),
341 Object::Array(obj) => obj.byterange(buffer),
342 Object::Integer(obj) => obj.byterange(buffer),
343 Object::Float(obj) => obj.byterange(buffer),
344 Object::Bool(obj) => obj.byterange(buffer),
345 Object::String(obj) => obj.byterange(buffer),
346 Object::UnionVectorTags(obj) => obj.byterange(buffer),
347 Object::UnionVectorValues(obj) => obj.byterange(buffer),
348 Object::Unknown(offset) => (*offset, *offset),
349 }
350 }
351}
352
353impl Byterange for OffsetObject<'_> {
354 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
355 (self.offset, self.offset + 4)
356 }
357}
358
359impl Byterange for VTableObject {
360 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
361 let size = self.get_vtable_size(buffer).unwrap();
362 (self.offset, self.offset + size as ByteIndex)
363 }
364}
365
366impl Byterange for TableObject {
367 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
368 (self.offset, self.offset + 4)
369 }
370}
371
372impl Byterange for StructObject {
373 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
374 let decl = self.resolve_declaration(buffer);
375 (self.offset, self.offset + decl.size)
376 }
377}
378
379impl Byterange for UnionTagObject {
380 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
381 (self.offset, self.offset + 1)
382 }
383}
384
385impl Byterange for UnionObject {
386 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
387 (self.offset, self.offset + 4)
388 }
389}
390
391impl Byterange for EnumObject {
392 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
393 let decl = self.resolve_declaration(buffer);
394 (self.offset, self.offset + decl.type_.byte_size())
395 }
396}
397
398impl Byterange for VectorObject<'_> {
399 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
400 (self.offset, self.offset)
401 }
402}
403
404impl Byterange for ArrayObject<'_> {
405 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
406 (self.offset, self.offset)
407 }
408}
409
410impl Byterange for IntegerObject {
411 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
412 (self.offset, self.offset + self.type_.byte_size())
413 }
414}
415
416impl Byterange for FloatObject {
417 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
418 (self.offset, self.offset + self.type_.byte_size())
419 }
420}
421
422impl Byterange for BoolObject {
423 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
424 (self.offset, self.offset + 1)
425 }
426}
427
428impl Byterange for StringObject {
429 fn byterange(&self, buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
430 (
431 self.offset,
432 self.offset + 4 + self.len(buffer).unwrap() as ByteIndex,
433 )
434 }
435}
436
437impl Byterange for UnionVectorTagsObject {
438 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
439 (self.tags_offset, self.tags_offset)
440 }
441}
442
443impl Byterange for UnionVectorValuesObject {
444 fn byterange(&self, _buffer: &InspectableFlatbuffer<'_>) -> (ByteIndex, ByteIndex) {
445 (self.values_offset, self.values_offset)
446 }
447}