1extern crate alloc;
2
3use core::alloc::Layout;
4
5use facet_core::{Def, Facet, Opaque, OpaqueUninit, Shape};
6
7mod value;
8pub use value::*;
9
10mod list;
11pub use list::*;
12
13mod map;
14pub use map::*;
15
16mod struct_;
17pub use struct_::*;
18
19mod enum_;
20pub use enum_::*;
21
22mod option;
23pub use option::*;
24
25#[non_exhaustive]
27pub enum PokeUninit<'mem> {
28 Scalar(PokeValueUninit<'mem>),
30 List(PokeListUninit<'mem>),
32 Map(PokeMapUninit<'mem>),
34 Struct(PokeStruct<'mem>),
36 Enum(PokeEnumNoVariant<'mem>),
38 Option(PokeOptionUninit<'mem>),
40}
41
42pub struct Guard {
44 ptr: *mut u8,
45 layout: Layout,
46 shape: &'static Shape,
47}
48
49impl Drop for Guard {
50 fn drop(&mut self) {
51 if self.layout.size() == 0 {
52 return;
53 }
54 unsafe { alloc::alloc::dealloc(self.ptr, self.layout) };
56 }
57}
58
59impl<'mem> PokeUninit<'mem> {
60 pub fn alloc<S: Facet>() -> (Self, Guard) {
62 let data = S::SHAPE.allocate();
63 let layout = Layout::new::<S>();
64 let guard = Guard {
65 ptr: data.as_mut_bytes(),
66 layout,
67 shape: S::SHAPE,
68 };
69 let poke = unsafe { Self::unchecked_new(data, S::SHAPE) };
70 (poke, guard)
71 }
72
73 pub fn alloc_shape(shape: &'static Shape) -> (Self, Guard) {
75 let data = shape.allocate();
76 let layout = shape.layout;
77 let guard = Guard {
78 ptr: data.as_mut_bytes(),
79 layout,
80 shape,
81 };
82 let poke = unsafe { Self::unchecked_new(data, shape) };
83 (poke, guard)
84 }
85
86 pub unsafe fn unchecked_new(data: OpaqueUninit<'mem>, shape: &'static Shape) -> Self {
93 match shape.def {
94 Def::Struct(struct_def) => {
95 PokeUninit::Struct(unsafe { PokeStruct::new(data, shape, struct_def) })
96 }
97 Def::Map(map_def) => {
98 let pmu = unsafe { PokeMapUninit::new(data, shape, map_def) };
99 PokeUninit::Map(pmu)
100 }
101 Def::List(list_def) => {
102 let plu = unsafe { PokeListUninit::new(data, shape, list_def) };
103 PokeUninit::List(plu)
104 }
105 Def::Scalar { .. } => PokeUninit::Scalar(unsafe { PokeValueUninit::new(data, shape) }),
106 Def::Enum(enum_def) => {
107 PokeUninit::Enum(unsafe { PokeEnumNoVariant::new(data, shape, enum_def) })
108 }
109 Def::Option(option_def) => {
110 let pou = unsafe { PokeOptionUninit::new(data, shape, option_def) };
111 PokeUninit::Option(pou)
112 }
113 _ => todo!("unsupported def: {:?}", shape.def),
114 }
115 }
116
117 pub fn into_struct(self) -> PokeStruct<'mem> {
119 match self {
120 PokeUninit::Struct(s) => s,
121 _ => panic!("expected Struct variant"),
122 }
123 }
124
125 pub fn into_list(self) -> PokeListUninit<'mem> {
127 match self {
128 PokeUninit::List(l) => l,
129 _ => panic!("expected List variant"),
130 }
131 }
132
133 pub fn into_map(self) -> PokeMapUninit<'mem> {
135 match self {
136 PokeUninit::Map(m) => m,
137 _ => panic!("expected Map variant"),
138 }
139 }
140
141 pub fn into_scalar(self) -> PokeValueUninit<'mem> {
143 match self {
144 PokeUninit::Scalar(s) => s,
145 _ => panic!("expected Scalar variant"),
146 }
147 }
148
149 pub fn into_enum(self) -> PokeEnumNoVariant<'mem> {
151 match self {
152 PokeUninit::Enum(e) => e,
153 _ => panic!("expected Enum variant"),
154 }
155 }
156
157 pub fn into_option(self) -> PokeOptionUninit<'mem> {
159 match self {
160 PokeUninit::Option(o) => o,
161 _ => panic!("expected Option variant"),
162 }
163 }
164
165 #[inline(always)]
167 pub fn into_value(self) -> PokeValueUninit<'mem> {
168 match self {
169 PokeUninit::Scalar(s) => s.into_value(),
170 PokeUninit::List(l) => l.into_value(),
171 PokeUninit::Map(m) => m.into_value(),
172 PokeUninit::Struct(s) => s.into_value(),
173 PokeUninit::Enum(e) => e.into_value(),
174 PokeUninit::Option(o) => o.into_value(),
175 }
176 }
177
178 #[inline(always)]
180 pub fn shape(&self) -> &'static Shape {
181 match self {
182 PokeUninit::Scalar(poke_value) => poke_value.shape(),
183 PokeUninit::List(poke_list_uninit) => poke_list_uninit.shape(),
184 PokeUninit::Map(poke_map_uninit) => poke_map_uninit.shape(),
185 PokeUninit::Struct(poke_struct) => poke_struct.shape(),
186 PokeUninit::Enum(poke_enum_no_variant) => poke_enum_no_variant.shape(),
187 PokeUninit::Option(poke_option_uninit) => poke_option_uninit.shape(),
188 }
189 }
190}
191
192#[derive(Clone, Copy, Default)]
194pub struct ISet(u64);
195
196impl ISet {
197 pub fn set(&mut self, index: usize) {
199 if index >= 64 {
200 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
201 }
202 self.0 |= 1 << index;
203 }
204
205 pub fn unset(&mut self, index: usize) {
207 if index >= 64 {
208 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
209 }
210 self.0 &= !(1 << index);
211 }
212
213 pub fn has(&self, index: usize) -> bool {
215 if index >= 64 {
216 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
217 }
218 (self.0 & (1 << index)) != 0
219 }
220
221 pub fn all_set(&self, count: usize) -> bool {
223 if count > 64 {
224 panic!("ISet can only track up to 64 fields. Count {count} is out of bounds.");
225 }
226 let mask = (1 << count) - 1;
227 self.0 & mask == mask
228 }
229}
230
231#[non_exhaustive]
233pub enum Poke<'mem> {
234 Scalar(PokeValue<'mem>),
236 List(PokeList<'mem>),
238 Map(PokeMap<'mem>),
240 Struct(PokeStruct<'mem>),
242 Enum(PokeEnum<'mem>),
244 Option(PokeOption<'mem>),
246}
247
248impl<'mem> Poke<'mem> {
249 pub unsafe fn unchecked_new(data: Opaque<'mem>, shape: &'static Shape) -> Self {
256 match shape.def {
257 Def::Struct(struct_def) => Poke::Struct(unsafe {
258 let mut ps =
259 PokeStruct::new(OpaqueUninit::new(data.as_mut_byte_ptr()), shape, struct_def);
260 for (i, _f) in ps.def().fields.iter().enumerate() {
261 ps.mark_initialized(i);
262 }
263 ps
264 }),
265 Def::Map(map_def) => {
266 let pm = unsafe { PokeMap::new(data, shape, map_def) };
267 Poke::Map(pm)
268 }
269 Def::List(list_def) => {
270 let pl = unsafe { PokeList::new(data, shape, list_def) };
271 Poke::List(pl)
272 }
273 Def::Scalar { .. } => Poke::Scalar(unsafe { PokeValue::new(data, shape) }),
274 Def::Enum(_enum_def) => {
275 todo!("we need to get the active variant somehow")
276 }
277 Def::Option(option_def) => {
278 let po = unsafe { PokeOption::new(data, shape, option_def) };
279 Poke::Option(po)
280 }
281 _ => todo!("unsupported def: {:?}", shape.def),
282 }
283 }
284
285 #[inline(always)]
287 pub fn borrow<T: Facet>(data: &'mem mut T) -> Poke<'mem> {
288 let shape = T::SHAPE;
289 let data = Opaque::new(data);
290 unsafe { Poke::unchecked_new(data, shape) }
291 }
292
293 pub fn into_scalar(self) -> PokeValue<'mem> {
295 match self {
296 Poke::Scalar(s) => s,
297 _ => panic!("expected Scalar variant"),
298 }
299 }
300
301 pub fn into_list(self) -> PokeList<'mem> {
303 match self {
304 Poke::List(l) => l,
305 _ => panic!("expected List variant"),
306 }
307 }
308
309 pub fn into_map(self) -> PokeMap<'mem> {
311 match self {
312 Poke::Map(m) => m,
313 _ => panic!("expected Map variant"),
314 }
315 }
316
317 pub fn into_struct(self) -> PokeStruct<'mem> {
319 match self {
320 Poke::Struct(s) => s,
321 _ => panic!("expected Struct variant"),
322 }
323 }
324
325 pub fn into_enum(self) -> PokeEnum<'mem> {
327 match self {
328 Poke::Enum(e) => e,
329 _ => panic!("expected Enum variant"),
330 }
331 }
332
333 pub fn into_option(self) -> PokeOption<'mem> {
335 match self {
336 Poke::Option(o) => o,
337 _ => panic!("expected Option variant"),
338 }
339 }
340
341 #[inline(always)]
343 pub fn shape(&self) -> &'static Shape {
344 match self {
345 Poke::Scalar(poke_value) => poke_value.shape(),
346 Poke::List(poke_list) => poke_list.shape(),
347 Poke::Map(poke_map) => poke_map.shape(),
348 Poke::Struct(poke_struct) => poke_struct.shape(),
349 Poke::Enum(poke_enum) => poke_enum.shape(),
350 Poke::Option(poke_option) => poke_option.shape(),
351 }
352 }
353}