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