Skip to main content

isr_core/
schema.rs

1//! Owned, serializable data model for a profile.
2//!
3//! These types form the on-disk schema. They are archived via rkyv and
4//! consumed through the typed view in [`crate::Profile`].
5
6use indexmap::IndexMap;
7use rkyv::{Archive, Deserialize, Serialize};
8
9/// A full profile: architecture, type definitions, and symbols.
10#[derive(Debug, Default, Archive, Serialize, Deserialize)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[rkyv(derive(Debug))]
13pub struct Profile {
14    /// Target architecture.
15    pub architecture: Architecture,
16
17    /// Enum definitions keyed by name.
18    pub enums: IndexMap<String, Enum>,
19
20    /// Struct definitions keyed by name.
21    pub structs: IndexMap<String, Struct>,
22
23    /// Symbol RVAs keyed by symbol name.
24    pub symbols: IndexMap<String, u64>,
25}
26
27/// Target CPU architecture.
28#[derive(Debug, Default, Archive, Serialize, Deserialize)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30#[rkyv(derive(Debug))]
31pub enum Architecture {
32    /// Unknown or unspecified architecture.
33    #[default]
34    Unknown,
35
36    /// 32-bit x86.
37    X86,
38
39    /// 64-bit x86.
40    Amd64,
41
42    /// 32-bit ARM.
43    Arm32,
44
45    /// 64-bit ARM.
46    Arm64,
47}
48
49//
50// Enum
51//
52
53/// Enum type.
54#[derive(Debug, Archive, Serialize, Deserialize)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56#[rkyv(derive(Debug))]
57pub struct Enum {
58    /// Underlying integer type of the enum.
59    pub subtype: Type,
60
61    /// Enum variants keyed by name.
62    pub fields: IndexMap<String, Variant>,
63}
64
65/// Enum variant.
66#[allow(missing_docs)]
67#[derive(Debug, Archive, Serialize, Deserialize)]
68#[cfg_attr(
69    feature = "serde",
70    derive(serde::Serialize, serde::Deserialize),
71    serde(untagged)
72)]
73#[rkyv(derive(Debug))]
74pub enum Variant {
75    U8(u8),
76    U16(u16),
77    U32(u32),
78    U64(u64),
79    U128(u128),
80    I8(i8),
81    I16(i16),
82    I32(i32),
83    I64(i64),
84    I128(i128),
85}
86
87//
88// Struct
89//
90
91/// Struct type.
92#[derive(Debug, Archive, Serialize, Deserialize)]
93#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
94#[rkyv(derive(Debug))]
95pub struct Struct {
96    /// Struct / class / union / interface tag.
97    pub kind: StructKind,
98
99    /// Size of the struct in bytes.
100    pub size: u64,
101
102    /// Fields keyed by name.
103    pub fields: IndexMap<String, Field>,
104}
105
106/// Struct kind.
107#[derive(Debug, Archive, Serialize, Deserialize)]
108#[cfg_attr(
109    feature = "serde",
110    derive(serde::Serialize, serde::Deserialize),
111    serde(rename_all = "snake_case")
112)]
113#[rkyv(derive(Debug))]
114pub enum StructKind {
115    /// A `struct`.
116    Struct,
117
118    /// A `class`.
119    Class,
120
121    /// A `union`.
122    Union,
123
124    /// An `interface`.
125    Interface,
126}
127
128/// Struct field.
129#[derive(Debug, Archive, Serialize, Deserialize)]
130#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131#[rkyv(derive(Debug))]
132pub struct Field {
133    /// Field offset (in bytes).
134    pub offset: u64,
135
136    /// Field type.
137    #[cfg_attr(feature = "serde", serde(rename = "type"))]
138    pub ty: Type,
139}
140
141//
142// Type
143//
144
145/// Type.
146#[derive(Debug, Archive, Serialize, Deserialize)]
147#[cfg_attr(
148    feature = "serde",
149    derive(serde::Serialize, serde::Deserialize),
150    serde(rename_all = "snake_case", tag = "kind")
151)]
152#[rkyv(derive(Debug))]
153pub enum Type {
154    /// Base type.
155    Base(Base),
156
157    /// Enum type.
158    Enum(EnumRef),
159
160    /// Struct type.
161    Struct(StructRef),
162
163    /// Array type.
164    Array(Array),
165
166    /// Pointer type.
167    Pointer(Pointer),
168
169    /// Bitfield type.
170    Bitfield(Bitfield),
171
172    /// Function type.
173    Function,
174}
175
176/// Base type.
177#[allow(missing_docs)]
178#[derive(Debug, Archive, Serialize, Deserialize)]
179#[cfg_attr(
180    feature = "serde",
181    derive(serde::Serialize, serde::Deserialize),
182    serde(rename_all = "snake_case", tag = "subkind")
183)]
184#[rkyv(derive(Debug))]
185pub enum Base {
186    /// Void type.
187    Void,
188
189    /// Boolean type.
190    Bool,
191
192    /// Character types.
193    Char8,
194    Char16,
195    Char32,
196
197    /// Signed integer types.
198    I8,
199    I16,
200    I32,
201    I64,
202    I128,
203
204    /// Unsigned integer types.
205    U8,
206    U16,
207    U32,
208    U64,
209    U128,
210
211    /// Floating-point types.
212    F8,
213    F16,
214    F32,
215    F64,
216    F128,
217}
218
219impl Base {
220    /// Returns the size of the base type in bytes.
221    pub fn size(&self) -> u64 {
222        match self {
223            Self::Void => 0,
224            Self::Char8 | Self::I8 | Self::U8 | Self::F8 | Self::Bool => 1,
225            Self::Char16 | Self::I16 | Self::U16 | Self::F16 => 2,
226            Self::Char32 | Self::I32 | Self::U32 | Self::F32 => 4,
227            Self::I64 | Self::U64 | Self::F64 => 8,
228            Self::I128 | Self::U128 | Self::F128 => 16,
229        }
230    }
231}
232
233impl ArchivedBase {
234    /// Returns the size of the base type in bytes.
235    pub fn size(&self) -> u64 {
236        match self {
237            Self::Void => 0,
238            Self::Char8 | Self::I8 | Self::U8 | Self::F8 | Self::Bool => 1,
239            Self::Char16 | Self::I16 | Self::U16 | Self::F16 => 2,
240            Self::Char32 | Self::I32 | Self::U32 | Self::F32 => 4,
241            Self::I64 | Self::U64 | Self::F64 => 8,
242            Self::I128 | Self::U128 | Self::F128 => 16,
243        }
244    }
245}
246
247/// Enum reference.
248#[derive(Debug, Archive, Serialize, Deserialize)]
249#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
250#[rkyv(derive(Debug))]
251pub struct EnumRef {
252    /// Name of the referenced enum.
253    pub name: String,
254}
255
256/// Struct reference.
257#[derive(Debug, Archive, Serialize, Deserialize)]
258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
259#[rkyv(derive(Debug))]
260pub struct StructRef {
261    /// Name of the referenced struct.
262    pub name: String,
263}
264
265/// Array type.
266#[derive(Debug, Archive, Serialize, Deserialize)]
267#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
268#[rkyv(
269    derive(Debug),
270    serialize_bounds(
271        __S: rkyv::ser::Writer + rkyv::ser::Allocator,
272        __S::Error: rkyv::rancor::Source,
273    ),
274    deserialize_bounds(
275        __D::Error: rkyv::rancor::Source,
276    ),
277    bytecheck(bounds(
278        __C: rkyv::validation::ArchiveContext,
279        __C::Error: rkyv::rancor::Source,
280    )
281))]
282pub struct Array {
283    /// Element type.
284    #[rkyv(omit_bounds)]
285    pub subtype: Box<Type>,
286
287    /// Array dimensions.
288    pub dims: Vec<u64>,
289}
290
291/// Bitfield type.
292#[derive(Debug, Archive, Serialize, Deserialize)]
293#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
294#[rkyv(
295    derive(Debug),
296    serialize_bounds(
297        __S: rkyv::ser::Writer + rkyv::ser::Allocator,
298        __S::Error: rkyv::rancor::Source,
299    ),
300    deserialize_bounds(
301        __D::Error: rkyv::rancor::Source,
302    ),
303    bytecheck(bounds(
304        __C: rkyv::validation::ArchiveContext,
305        __C::Error: rkyv::rancor::Source,
306    )
307))]
308pub struct Bitfield {
309    /// Bitfield subtype.
310    #[rkyv(omit_bounds)]
311    pub subtype: Box<Type>,
312
313    /// Bit length.
314    pub bit_length: u64,
315
316    /// Bit position.
317    pub bit_position: u64,
318}
319
320/// Pointer type.
321#[derive(Debug, Archive, Serialize, Deserialize)]
322#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
323#[rkyv(
324    derive(Debug),
325    serialize_bounds(
326        __S: rkyv::ser::Writer + rkyv::ser::Allocator,
327        __S::Error: rkyv::rancor::Source,
328    ),
329    deserialize_bounds(
330        __D::Error: rkyv::rancor::Source,
331    ),
332    bytecheck(bounds(
333        __C: rkyv::validation::ArchiveContext,
334        __C::Error: rkyv::rancor::Source,
335    )
336))]
337pub struct Pointer {
338    /// Type of the pointed value.
339    #[rkyv(omit_bounds)]
340    pub subtype: Box<Type>,
341
342    /// Size of the pointer in bytes.
343    pub size: u64,
344}