recordkeeper_data_model/
lib.rs1use std::{any::TypeId, marker::PhantomData};
4
5pub trait Model: 'static {
7 fn model() -> TypeModel;
8}
9
10pub type ModelName = &'static str;
11
12#[derive(Debug)]
15pub struct StructModel {
16 pub name: ModelName,
20 pub type_id: TypeId,
23 pub total_len: usize,
24 pub fields: Vec<FieldModel>,
25}
26
27pub struct StructModelBuilder(StructModel);
28
29#[derive(Debug)]
31pub struct FieldModel {
32 pub name: ModelName,
33 pub type_model: TypeModel,
34 pub offset: usize,
35 pub size: usize,
36}
37
38#[derive(Debug)]
39pub enum TypeModel {
40 Empty,
42 Struct(Box<StructModel>),
44 Array(Box<(TypeModel, usize)>),
46 Primitive(ModelName),
48}
49
50impl StructModel {
51 pub fn new_opaque(name: ModelName, type_id: TypeId, size: usize) -> Self {
56 Self {
57 name,
58 type_id,
59 total_len: size,
60 fields: Vec::new(),
61 }
62 }
63
64 pub fn new_builder(name: ModelName, type_id: TypeId) -> StructModelBuilder {
68 StructModelBuilder(StructModel {
69 name,
70 type_id,
71 total_len: 0,
72 fields: Vec::new(),
73 })
74 }
75}
76
77impl StructModelBuilder {
78 pub fn add_field(
79 &mut self,
80 name: ModelName,
81 type_model: TypeModel,
82 offset: usize,
83 size: usize,
84 ) -> &mut Self {
85 if offset < self.0.total_len {
86 self.0.total_len = offset;
87 }
88 self.0.fields.push(FieldModel {
89 name,
90 offset,
91 type_model,
92 size,
93 });
94 self.0.total_len += size;
95 self
96 }
97
98 pub fn set_total_len(&mut self, size: usize) -> &mut Self {
99 assert!(size >= self.0.total_len);
100 self.0.total_len = size;
101 self
102 }
103
104 pub fn build(self) -> StructModel {
105 self.0
106 }
107}
108
109macro_rules! builtin_impl {
110 ($($types:tt ) *) => {
111 $(
112 impl Model for $types {
113 fn model() -> TypeModel {
114 TypeModel::Primitive(stringify!($types))
115 }
116 }
117 )*
118 };
119}
120
121builtin_impl!(bool u8 i8 u64 i64 f64 u32 i32 f32 u16 i16);
122
123impl<T, const N: usize> Model for [T; N]
124where
125 T: Model,
126{
127 fn model() -> TypeModel {
128 TypeModel::Array(Box::new((T::model(), N)))
129 }
130}
131
132impl<T, const N: usize> Model for Box<[T; N]>
133where
134 T: Model,
135{
136 fn model() -> TypeModel {
137 TypeModel::Array(Box::new((T::model(), N)))
138 }
139}
140
141impl<T: 'static> Model for PhantomData<T> {
142 fn model() -> TypeModel {
143 TypeModel::Empty
144 }
145}