plotnik_bytecode/bytecode/
type_meta.rs

1//! Type metadata definitions for bytecode format.
2
3use super::{StringId, TypeId};
4
5// Re-export the shared TypeKind
6pub use crate::type_system::TypeKind;
7
8/// Convenience aliases for bytecode-specific naming (ArrayStar/ArrayPlus).
9impl TypeKind {
10    /// Alias for `ArrayZeroOrMore` (T*).
11    pub const ARRAY_STAR: Self = Self::ArrayZeroOrMore;
12    /// Alias for `ArrayOneOrMore` (T+).
13    pub const ARRAY_PLUS: Self = Self::ArrayOneOrMore;
14}
15
16/// Type definition entry (4 bytes).
17///
18/// Semantics of `data` and `count` depend on `kind`:
19/// - Wrappers (Optional, ArrayStar, ArrayPlus): `data` = inner TypeId, `count` = 0
20/// - Struct/Enum: `data` = member index, `count` = member count
21/// - Alias: `data` = target TypeId, `count` = 0
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23#[repr(C)]
24pub struct TypeDef {
25    /// For wrappers/alias: inner/target TypeId.
26    /// For Struct/Enum: index into TypeMembers section.
27    data: u16,
28    /// Member count (0 for wrappers/alias, field/variant count for composites).
29    count: u8,
30    /// TypeKind discriminant.
31    kind: u8,
32}
33
34const _: () = assert!(std::mem::size_of::<TypeDef>() == 4);
35
36/// Structured view of TypeDef data, eliminating the need for Option-returning accessors.
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub enum TypeData {
39    /// Primitive types: Void, Node, String.
40    Primitive(TypeKind),
41    /// Wrapper types: Optional, ArrayZeroOrMore, ArrayOneOrMore, Alias.
42    Wrapper { kind: TypeKind, inner: TypeId },
43    /// Composite types: Struct, Enum.
44    Composite {
45        kind: TypeKind,
46        member_start: u16,
47        member_count: u8,
48    },
49}
50
51impl TypeDef {
52    /// Create a builtin type (Void, Node, String).
53    pub fn builtin(kind: TypeKind) -> Self {
54        Self {
55            data: 0,
56            count: 0,
57            kind: kind as u8,
58        }
59    }
60
61    /// Create a placeholder slot (to be filled later).
62    pub fn placeholder() -> Self {
63        Self {
64            data: 0,
65            count: 0,
66            kind: 0,
67        }
68    }
69
70    /// Create a wrapper type (Optional, ArrayStar, ArrayPlus).
71    pub fn wrapper(kind: TypeKind, inner: TypeId) -> Self {
72        Self {
73            data: inner.0,
74            count: 0,
75            kind: kind as u8,
76        }
77    }
78
79    /// Create a composite type (Struct, Enum).
80    pub fn composite(kind: TypeKind, member_start: u16, member_count: u8) -> Self {
81        Self {
82            data: member_start,
83            count: member_count,
84            kind: kind as u8,
85        }
86    }
87
88    /// Create an optional wrapper type.
89    pub fn optional(inner: TypeId) -> Self {
90        Self::wrapper(TypeKind::Optional, inner)
91    }
92
93    /// Create an alias type.
94    pub fn alias(target: TypeId) -> Self {
95        Self::wrapper(TypeKind::Alias, target)
96    }
97
98    /// Create an ArrayStar (T*) wrapper type.
99    pub fn array_star(element: TypeId) -> Self {
100        Self::wrapper(TypeKind::ARRAY_STAR, element)
101    }
102
103    /// Create an ArrayPlus (T+) wrapper type.
104    pub fn array_plus(element: TypeId) -> Self {
105        Self::wrapper(TypeKind::ARRAY_PLUS, element)
106    }
107
108    /// Create a struct type.
109    pub fn struct_type(member_start: u16, member_count: u8) -> Self {
110        Self::composite(TypeKind::Struct, member_start, member_count)
111    }
112
113    /// Create an enum type.
114    pub fn enum_type(member_start: u16, member_count: u8) -> Self {
115        Self::composite(TypeKind::Enum, member_start, member_count)
116    }
117
118    /// Decode from 4 bytes (crate-internal deserialization).
119    pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
120        Self {
121            data: u16::from_le_bytes([bytes[0], bytes[1]]),
122            count: bytes[2],
123            kind: bytes[3],
124        }
125    }
126
127    /// Encode to 4 bytes.
128    pub fn to_bytes(&self) -> [u8; 4] {
129        let mut bytes = [0u8; 4];
130        bytes[0..2].copy_from_slice(&self.data.to_le_bytes());
131        bytes[2] = self.count;
132        bytes[3] = self.kind;
133        bytes
134    }
135
136    /// Classify this type definition into a structured enum.
137    ///
138    /// # Panics
139    /// Panics if the kind byte is invalid (corrupted bytecode).
140    pub fn classify(&self) -> TypeData {
141        let kind = TypeKind::from_u8(self.kind)
142            .unwrap_or_else(|| panic!("invalid TypeKind byte: {}", self.kind));
143        match kind {
144            TypeKind::Void | TypeKind::Node | TypeKind::String => TypeData::Primitive(kind),
145            TypeKind::Optional
146            | TypeKind::ArrayZeroOrMore
147            | TypeKind::ArrayOneOrMore
148            | TypeKind::Alias => TypeData::Wrapper {
149                kind,
150                inner: TypeId(self.data),
151            },
152            TypeKind::Struct | TypeKind::Enum => TypeData::Composite {
153                kind,
154                member_start: self.data,
155                member_count: self.count,
156            },
157        }
158    }
159}
160
161/// Maps a name to a type (4 bytes).
162///
163/// Only named types (definitions, aliases) have entries here.
164/// Entries are sorted lexicographically by name for binary search.
165#[derive(Clone, Copy, Debug, PartialEq, Eq)]
166#[repr(C)]
167pub struct TypeName {
168    /// StringId of the type name.
169    pub name: StringId,
170    /// TypeId this name refers to.
171    pub type_id: TypeId,
172}
173
174const _: () = assert!(std::mem::size_of::<TypeName>() == 4);
175
176impl TypeName {
177    /// Create a new type name entry.
178    pub fn new(name: StringId, type_id: TypeId) -> Self {
179        Self { name, type_id }
180    }
181
182    /// Encode to 4 bytes.
183    pub fn to_bytes(&self) -> [u8; 4] {
184        let mut bytes = [0u8; 4];
185        bytes[0..2].copy_from_slice(&self.name.get().to_le_bytes());
186        bytes[2..4].copy_from_slice(&self.type_id.0.to_le_bytes());
187        bytes
188    }
189}
190
191/// Field or variant entry (4 bytes).
192#[derive(Clone, Copy, Debug, PartialEq, Eq)]
193#[repr(C)]
194pub struct TypeMember {
195    /// Field/variant name.
196    pub name: StringId,
197    /// Type of this field/variant.
198    pub type_id: TypeId,
199}
200
201const _: () = assert!(std::mem::size_of::<TypeMember>() == 4);
202
203impl TypeMember {
204    /// Create a new type member entry.
205    pub fn new(name: StringId, type_id: TypeId) -> Self {
206        Self { name, type_id }
207    }
208
209    /// Encode to 4 bytes.
210    pub fn to_bytes(&self) -> [u8; 4] {
211        let mut bytes = [0u8; 4];
212        bytes[0..2].copy_from_slice(&self.name.get().to_le_bytes());
213        bytes[2..4].copy_from_slice(&self.type_id.0.to_le_bytes());
214        bytes
215    }
216}