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
25mod smart_pointer;
26pub use smart_pointer::*;
27
28#[non_exhaustive]
30pub enum PokeUninit<'mem> {
31 Scalar(PokeValueUninit<'mem>),
33 List(PokeListUninit<'mem>),
35 Map(PokeMapUninit<'mem>),
37 Struct(PokeStruct<'mem>),
39 Enum(PokeEnumNoVariant<'mem>),
41 Option(PokeOptionUninit<'mem>),
43 SmartPointer(PokeSmartPointerUninit<'mem>),
45}
46
47pub struct Guard {
49 ptr: *mut u8,
50 layout: Layout,
51 shape: &'static Shape,
52}
53
54impl Drop for Guard {
55 fn drop(&mut self) {
56 if self.layout.size() == 0 {
57 return;
58 }
59 unsafe { alloc::alloc::dealloc(self.ptr, self.layout) };
61 }
62}
63
64impl<'mem> PokeUninit<'mem> {
65 pub fn alloc<S: Facet>() -> (Self, Guard) {
67 let data = S::SHAPE.allocate();
68 let layout = Layout::new::<S>();
69 let guard = Guard {
70 ptr: data.as_mut_bytes(),
71 layout,
72 shape: S::SHAPE,
73 };
74 let poke = unsafe { Self::unchecked_new(data, S::SHAPE) };
75 (poke, guard)
76 }
77
78 pub fn alloc_shape(shape: &'static Shape) -> (Self, Guard) {
80 let data = shape.allocate();
81 let layout = shape.layout;
82 let guard = Guard {
83 ptr: data.as_mut_bytes(),
84 layout,
85 shape,
86 };
87 let poke = unsafe { Self::unchecked_new(data, shape) };
88 (poke, guard)
89 }
90
91 pub unsafe fn unchecked_new(data: OpaqueUninit<'mem>, shape: &'static Shape) -> Self {
98 match shape.def {
99 Def::Struct(struct_def) => {
100 PokeUninit::Struct(unsafe { PokeStruct::new(data, shape, struct_def) })
101 }
102 Def::Map(map_def) => {
103 let pmu = unsafe { PokeMapUninit::new(data, shape, map_def) };
104 PokeUninit::Map(pmu)
105 }
106 Def::List(list_def) => {
107 let plu = unsafe { PokeListUninit::new(data, shape, list_def) };
108 PokeUninit::List(plu)
109 }
110 Def::Scalar { .. } => PokeUninit::Scalar(unsafe { PokeValueUninit::new(data, shape) }),
111 Def::Enum(enum_def) => {
112 PokeUninit::Enum(unsafe { PokeEnumNoVariant::new(data, shape, enum_def) })
113 }
114 Def::Option(option_def) => {
115 let pou = unsafe { PokeOptionUninit::new(data, shape, option_def) };
116 PokeUninit::Option(pou)
117 }
118 Def::SmartPointer(smart_pointer_def) => {
119 let psu = unsafe { PokeSmartPointerUninit::new(data, shape, smart_pointer_def) };
120 PokeUninit::SmartPointer(psu)
121 }
122 _ => todo!("unsupported def: {:?}", shape.def),
123 }
124 }
125
126 pub fn into_struct(self) -> PokeStruct<'mem> {
128 match self {
129 PokeUninit::Struct(s) => s,
130 _ => panic!("expected Struct variant"),
131 }
132 }
133
134 pub fn into_list(self) -> PokeListUninit<'mem> {
136 match self {
137 PokeUninit::List(l) => l,
138 _ => panic!("expected List variant"),
139 }
140 }
141
142 pub fn into_map(self) -> PokeMapUninit<'mem> {
144 match self {
145 PokeUninit::Map(m) => m,
146 _ => panic!("expected Map variant"),
147 }
148 }
149
150 pub fn into_smart_pointer(self) -> PokeSmartPointerUninit<'mem> {
152 match self {
153 PokeUninit::SmartPointer(s) => s,
154 _ => panic!("expected SmartPointer variant"),
155 }
156 }
157
158 pub fn into_scalar(self) -> PokeValueUninit<'mem> {
160 match self {
161 PokeUninit::Scalar(s) => s,
162 _ => panic!("expected Scalar variant"),
163 }
164 }
165
166 pub fn into_enum(self) -> PokeEnumNoVariant<'mem> {
168 match self {
169 PokeUninit::Enum(e) => e,
170 _ => panic!("expected Enum variant"),
171 }
172 }
173
174 pub fn into_option(self) -> PokeOptionUninit<'mem> {
176 match self {
177 PokeUninit::Option(o) => o,
178 _ => panic!("expected Option variant"),
179 }
180 }
181
182 #[inline(always)]
184 pub fn into_value(self) -> PokeValueUninit<'mem> {
185 match self {
186 PokeUninit::Scalar(s) => s.into_value(),
187 PokeUninit::List(l) => l.into_value(),
188 PokeUninit::Map(m) => m.into_value(),
189 PokeUninit::Struct(s) => s.into_value(),
190 PokeUninit::Enum(e) => e.into_value(),
191 PokeUninit::Option(o) => o.into_value(),
192 PokeUninit::SmartPointer(s) => s.into_value(),
193 }
194 }
195
196 #[inline(always)]
198 pub fn shape(&self) -> &'static Shape {
199 match self {
200 PokeUninit::Scalar(poke_value) => poke_value.shape(),
201 PokeUninit::List(poke_list_uninit) => poke_list_uninit.shape(),
202 PokeUninit::Map(poke_map_uninit) => poke_map_uninit.shape(),
203 PokeUninit::Struct(poke_struct) => poke_struct.shape(),
204 PokeUninit::Enum(poke_enum_no_variant) => poke_enum_no_variant.shape(),
205 PokeUninit::Option(poke_option_uninit) => poke_option_uninit.shape(),
206 PokeUninit::SmartPointer(poke_smart_pointer_uninit) => {
207 poke_smart_pointer_uninit.shape()
208 }
209 }
210 }
211}
212
213#[derive(Clone, Copy, Default)]
215pub struct ISet(u64);
216
217impl ISet {
218 pub fn set(&mut self, index: usize) {
220 if index >= 64 {
221 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
222 }
223 self.0 |= 1 << index;
224 }
225
226 pub fn unset(&mut self, index: usize) {
228 if index >= 64 {
229 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
230 }
231 self.0 &= !(1 << index);
232 }
233
234 pub fn has(&self, index: usize) -> bool {
236 if index >= 64 {
237 panic!("ISet can only track up to 64 fields. Index {index} is out of bounds.");
238 }
239 (self.0 & (1 << index)) != 0
240 }
241
242 pub fn all_set(&self, count: usize) -> bool {
244 if count > 64 {
245 panic!("ISet can only track up to 64 fields. Count {count} is out of bounds.");
246 }
247 let mask = (1 << count) - 1;
248 self.0 & mask == mask
249 }
250}
251
252#[non_exhaustive]
254pub enum Poke<'mem> {
255 Scalar(PokeValue<'mem>),
257 List(PokeList<'mem>),
259 Map(PokeMap<'mem>),
261 Struct(PokeStruct<'mem>),
263 Enum(PokeEnum<'mem>),
265 Option(PokeOption<'mem>),
267 SmartPointer(PokeSmartPointer<'mem>),
269}
270
271impl<'mem> Poke<'mem> {
272 pub unsafe fn unchecked_new(data: Opaque<'mem>, shape: &'static Shape) -> Self {
279 match shape.def {
280 Def::Struct(struct_def) => Poke::Struct(unsafe {
281 let mut ps =
282 PokeStruct::new(OpaqueUninit::new(data.as_mut_byte_ptr()), shape, struct_def);
283 for (i, _f) in ps.def().fields.iter().enumerate() {
284 ps.mark_initialized(i);
285 }
286 ps
287 }),
288 Def::Map(map_def) => {
289 let pm = unsafe { PokeMap::new(data, shape, map_def) };
290 Poke::Map(pm)
291 }
292 Def::List(list_def) => {
293 let pl = unsafe { PokeList::new(data, shape, list_def) };
294 Poke::List(pl)
295 }
296 Def::Scalar { .. } => Poke::Scalar(unsafe { PokeValue::new(data, shape) }),
297 Def::Enum(_enum_def) => {
298 todo!("we need to get the active variant somehow")
299 }
300 Def::Option(option_def) => {
301 let po = unsafe { PokeOption::new(data, shape, option_def) };
302 Poke::Option(po)
303 }
304 Def::SmartPointer(smart_pointer_def) => {
305 let ps = unsafe { PokeSmartPointer::new(data, shape, smart_pointer_def) };
306 Poke::SmartPointer(ps)
307 }
308 _ => todo!("unsupported def: {:?}", shape.def),
309 }
310 }
311
312 #[inline(always)]
314 pub fn borrow<T: Facet>(data: &'mem mut T) -> Poke<'mem> {
315 let shape = T::SHAPE;
316 let data = Opaque::new(data);
317 unsafe { Poke::unchecked_new(data, shape) }
318 }
319
320 pub fn into_smart_pointer(self) -> PokeSmartPointer<'mem> {
322 match self {
323 Poke::SmartPointer(s) => s,
324 _ => panic!("expected SmartPointer variant"),
325 }
326 }
327
328 pub fn into_scalar(self) -> PokeValue<'mem> {
330 match self {
331 Poke::Scalar(s) => s,
332 _ => panic!("expected Scalar variant"),
333 }
334 }
335
336 pub fn into_list(self) -> PokeList<'mem> {
338 match self {
339 Poke::List(l) => l,
340 _ => panic!("expected List variant"),
341 }
342 }
343
344 pub fn into_map(self) -> PokeMap<'mem> {
346 match self {
347 Poke::Map(m) => m,
348 _ => panic!("expected Map variant"),
349 }
350 }
351
352 pub fn into_struct(self) -> PokeStruct<'mem> {
354 match self {
355 Poke::Struct(s) => s,
356 _ => panic!("expected Struct variant"),
357 }
358 }
359
360 pub fn into_enum(self) -> PokeEnum<'mem> {
362 match self {
363 Poke::Enum(e) => e,
364 _ => panic!("expected Enum variant"),
365 }
366 }
367
368 pub fn into_option(self) -> PokeOption<'mem> {
370 match self {
371 Poke::Option(o) => o,
372 _ => panic!("expected Option variant"),
373 }
374 }
375
376 #[inline(always)]
378 pub fn shape(&self) -> &'static Shape {
379 match self {
380 Poke::Scalar(poke_value) => poke_value.shape(),
381 Poke::List(poke_list) => poke_list.shape(),
382 Poke::Map(poke_map) => poke_map.shape(),
383 Poke::Struct(poke_struct) => poke_struct.shape(),
384 Poke::Enum(poke_enum) => poke_enum.shape(),
385 Poke::Option(poke_option) => poke_option.shape(),
386 Poke::SmartPointer(poke_smart_pointer) => poke_smart_pointer.shape(),
387 }
388 }
389}