1use crate::vec;
2
3use crate::ArrayReader;
4use crate::Decode;
5use crate::Error;
6use crate::TupleReader;
7use crate::ir;
8use crate::layout;
9
10pub trait Visitor<'t, B>
11where
12 B: bytes::Buf + Clone,
13{
14 type Res;
15
16 fn get_ty(&self, name: &ir::Path) -> &'t ir::Ty;
17
18 fn get_mat_ty(&self, ty: &'t ir::Ty) -> &'t ir::Ty {
19 let mut ty = ty;
20 while let ir::TyKind::Ident(name) = &ty.kind {
21 ty = self.get_ty(name);
22 }
23 ty
24 }
25
26 fn visit(&mut self, buf: B, ty: &'t ir::Ty) -> Result<Self::Res, crate::Error> {
27 let ty = self.get_mat_ty(ty);
28
29 self.visit_concrete(buf, ty)
30 }
31
32 fn visit_concrete(&mut self, buf: B, ty: &'t ir::Ty) -> Result<Self::Res, crate::Error> {
33 match &ty.kind {
34 ir::TyKind::Primitive(ir::TyPrimitive::bool) => {
35 self.visit_bool(bool::decode(buf.chunk())?)
36 }
37 ir::TyKind::Primitive(ir::TyPrimitive::int8) => {
38 self.visit_int8(i8::decode(buf.chunk())?)
39 }
40 ir::TyKind::Primitive(ir::TyPrimitive::uint8) => {
41 self.visit_uint8(u8::decode(buf.chunk())?)
42 }
43 ir::TyKind::Primitive(ir::TyPrimitive::int16) => {
44 self.visit_int16(i16::decode(buf.chunk())?)
45 }
46 ir::TyKind::Primitive(ir::TyPrimitive::uint16) => {
47 self.visit_uint16(u16::decode(buf.chunk())?)
48 }
49 ir::TyKind::Primitive(ir::TyPrimitive::int32) => {
50 self.visit_int32(i32::decode(buf.chunk())?)
51 }
52 ir::TyKind::Primitive(ir::TyPrimitive::uint32) => {
53 self.visit_uint32(u32::decode(buf.chunk())?)
54 }
55 ir::TyKind::Primitive(ir::TyPrimitive::float32) => {
56 self.visit_float32(f32::decode(buf.chunk())?)
57 }
58 ir::TyKind::Primitive(ir::TyPrimitive::int64) => {
59 self.visit_int64(i64::decode(buf.chunk())?)
60 }
61 ir::TyKind::Primitive(ir::TyPrimitive::uint64) => {
62 self.visit_uint64(u64::decode(buf.chunk())?)
63 }
64 ir::TyKind::Primitive(ir::TyPrimitive::float64) => {
65 self.visit_float64(f64::decode(buf.chunk())?)
66 }
67 ir::TyKind::Primitive(ir::TyPrimitive::text) => {
68 let (offset, len) = ArrayReader::<&[u8]>::read_head(buf.chunk());
69
70 let mut buf = buf;
71 buf.advance(offset);
72
73 self.visit_text(buf, len)
74 }
75 ir::TyKind::Tuple(ty_fields) => {
76 let reader = TupleReader::new_for_ty(buf, ty);
77
78 let fields = ty_fields
79 .iter()
80 .enumerate()
81 .map(|(i, t)| (reader.get_field(i), t));
82 self.visit_tuple(fields)
83 }
84 ir::TyKind::Array(ty_items) => {
85 let reader = ArrayReader::new_for_ty(buf, ty);
86 self.visit_array(reader, ty_items)
87 }
88 ir::TyKind::Enum(variants) => {
89 let head = layout::enum_head_format(variants, &ty.variants_recursive);
90
91 let mut buf = buf;
92
93 let mut tag_bytes = vec![0; 8];
94 buf.copy_to_slice(&mut tag_bytes[0..head.tag_bytes as usize]);
95 tag_bytes.resize(8, 0);
96 let tag = u64::from_le_bytes(tag_bytes.try_into().unwrap()) as usize;
97
98 let variant = variants.get(tag).unwrap();
99
100 let variant_format = layout::enum_variant_format(&head, &variant.ty);
101
102 let mut buf_inner = buf;
103 if head.has_ptr {
104 if variant_format.is_unit {
105 } else {
107 let ptr = buf_inner.clone().get_u32_le() as usize;
109
110 buf_inner.advance(ptr);
111 }
112 } else {
113 };
115
116 self.visit_enum(tag, buf_inner, variants)
117 }
118
119 ir::TyKind::Function(..) => Err(Error::InvalidType),
120 ir::TyKind::Ident(..) => Err(Error::Bug),
121 }
122 }
123
124 fn visit_bool(&mut self, v: bool) -> Result<Self::Res, crate::Error>;
125 fn visit_int8(&mut self, v: i8) -> Result<Self::Res, crate::Error>;
126 fn visit_int16(&mut self, v: i16) -> Result<Self::Res, crate::Error>;
127 fn visit_int32(&mut self, v: i32) -> Result<Self::Res, crate::Error>;
128 fn visit_int64(&mut self, v: i64) -> Result<Self::Res, crate::Error>;
129 fn visit_uint8(&mut self, v: u8) -> Result<Self::Res, crate::Error>;
130 fn visit_uint16(&mut self, v: u16) -> Result<Self::Res, crate::Error>;
131 fn visit_uint32(&mut self, v: u32) -> Result<Self::Res, crate::Error>;
132 fn visit_uint64(&mut self, v: u64) -> Result<Self::Res, crate::Error>;
133 fn visit_float32(&mut self, v: f32) -> Result<Self::Res, crate::Error>;
134 fn visit_float64(&mut self, v: f64) -> Result<Self::Res, crate::Error>;
135 fn visit_text(&mut self, contents: B, len: usize) -> Result<Self::Res, crate::Error>;
136
137 fn visit_tuple(
138 &mut self,
139 fields: impl Iterator<Item = (B, &'t ir::TyTupleField)>,
140 ) -> Result<Self::Res, crate::Error>;
141
142 fn visit_array(
143 &mut self,
144 items: impl Iterator<Item = B>,
145 ty_items: &'t ir::Ty,
146 ) -> Result<Self::Res, crate::Error>;
147
148 fn visit_enum(
149 &mut self,
150 tag: usize,
151 inner: B,
152 ty_variants: &'t [ir::TyEnumVariant],
153 ) -> Result<Self::Res, crate::Error>;
154}