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