1use core::{cmp::Ordering, marker::PhantomData, ptr::NonNull};
2use facet_core::{
3 Def, Facet, PointerType, PtrConst, Shape, StructKind, Type, TypeNameOpts, UserType, ValueVTable,
4};
5
6use crate::{PeekNdArray, PeekSet, ReflectError, ScalarType};
7
8use super::{
9 ListLikeDef, PeekEnum, PeekList, PeekListLike, PeekMap, PeekOption, PeekPointer, PeekStruct,
10 PeekTuple, tuple::TupleType,
11};
12
13#[derive(Clone, Copy, PartialEq, Eq, Hash)]
15pub struct ValueId {
16 pub(crate) shape: &'static Shape,
17 pub(crate) ptr: *const u8,
18}
19
20impl ValueId {
21 #[inline]
22 pub(crate) fn new(shape: &'static Shape, ptr: *const u8) -> Self {
23 Self { shape, ptr }
24 }
25}
26
27impl core::fmt::Display for ValueId {
28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29 write!(f, "{}@{:p}", self.shape, self.ptr)
30 }
31}
32
33impl core::fmt::Debug for ValueId {
34 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 core::fmt::Display::fmt(self, f)
36 }
37}
38
39#[derive(Clone, Copy)]
45pub struct Peek<'mem, 'facet> {
46 pub(crate) data: PtrConst<'mem>,
48
49 pub(crate) shape: &'static Shape,
51
52 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
53}
54
55impl<'mem, 'facet> Peek<'mem, 'facet> {
56 pub fn new<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Self {
58 Self {
59 data: PtrConst::new(NonNull::from(t)),
60 shape: T::SHAPE,
61 invariant: PhantomData,
62 }
63 }
64
65 pub unsafe fn unchecked_new(data: PtrConst<'mem>, shape: &'static Shape) -> Self {
74 Self {
75 data,
76 shape,
77 invariant: PhantomData,
78 }
79 }
80
81 #[inline(always)]
83 pub fn vtable(&self) -> &'static ValueVTable {
84 &self.shape.vtable
85 }
86
87 #[inline]
89 pub fn id(&self) -> ValueId {
90 ValueId::new(self.shape, self.data.as_byte_ptr())
91 }
92
93 #[inline]
95 pub fn ptr_eq(&self, other: &Peek<'_, '_>) -> bool {
96 self.data.as_byte_ptr() == other.data.as_byte_ptr()
97 }
98
99 #[inline]
105 pub fn partial_eq(&self, other: &Peek<'_, '_>) -> Result<bool, ReflectError> {
106 if let Some(f) = self.vtable().partial_eq {
107 if self.shape == other.shape {
108 return Ok(unsafe { f(self.data, other.data) });
109 } else {
110 return Err(ReflectError::WrongShape {
111 expected: self.shape,
112 actual: other.shape,
113 });
114 }
115 }
116
117 Err(ReflectError::OperationFailed {
118 shape: self.shape(),
119 operation: "partial_eq",
120 })
121 }
122
123 #[inline]
129 pub fn partial_cmp(&self, other: &Peek<'_, '_>) -> Result<Option<Ordering>, ReflectError> {
130 if let Some(f) = self.vtable().partial_ord {
131 if self.shape == other.shape {
132 return Ok(unsafe { f(self.data, other.data) });
133 } else {
134 return Err(ReflectError::WrongShape {
135 expected: self.shape,
136 actual: other.shape,
137 });
138 }
139 }
140
141 Err(ReflectError::OperationFailed {
142 shape: self.shape(),
143 operation: "partial_cmp",
144 })
145 }
146 #[inline(always)]
152 pub fn hash(&self, hasher: &mut dyn core::hash::Hasher) -> Result<(), ReflectError> {
153 if let Some(hash_fn) = self.vtable().hash {
154 unsafe {
155 hash_fn(self.data, hasher);
156 return Ok(());
157 };
158 }
159
160 Err(ReflectError::OperationFailed {
161 shape: self.shape(),
162 operation: "hash",
163 })
164 }
165
166 #[inline(always)]
177 pub fn type_name(
178 &self,
179 f: &mut core::fmt::Formatter<'_>,
180 opts: TypeNameOpts,
181 ) -> core::fmt::Result {
182 self.shape.vtable.type_name()(f, opts)
183 }
184
185 #[inline(always)]
187 pub const fn shape(&self) -> &'static Shape {
188 self.shape
189 }
190
191 #[inline(always)]
193 pub const fn data(&self) -> PtrConst<'mem> {
194 self.data
195 }
196
197 #[inline]
199 pub fn scalar_type(&self) -> Option<ScalarType> {
200 ScalarType::try_from_shape(self.shape)
201 }
202
203 #[inline]
209 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&T, ReflectError> {
210 if self.shape != T::SHAPE {
211 Err(ReflectError::WrongShape {
212 expected: self.shape,
213 actual: T::SHAPE,
214 })
215 } else {
216 Ok(unsafe { self.data.get::<T>() })
217 }
218 }
219
220 pub fn as_str(&self) -> Option<&'mem str> {
223 let peek = self.innermost_peek();
224 if let Some(ScalarType::Str) = peek.scalar_type() {
225 unsafe { Some(peek.data.get::<&str>()) }
226 } else if let Some(ScalarType::String) = peek.scalar_type() {
227 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
228 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
229 let target_shape = vpt.target;
230 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
231 unsafe { Some(peek.data.get::<&str>()) }
232 } else {
233 None
234 }
235 } else {
236 None
237 }
238 }
239
240 #[inline]
243 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
244 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
246 let target_shape = vpt.target;
247 if let Def::Slice(sd) = target_shape.def {
248 if sd.t().is_type::<u8>() {
249 unsafe { return Some(self.data.get::<&[u8]>()) }
250 }
251 }
252 }
253 None
254 }
255
256 #[inline]
258 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
259 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
260 Ok(PeekStruct { value: self, ty })
261 } else {
262 Err(ReflectError::WasNotA {
263 expected: "struct",
264 actual: self.shape,
265 })
266 }
267 }
268
269 #[inline]
271 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
272 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
273 Ok(PeekEnum { value: self, ty })
274 } else {
275 Err(ReflectError::WasNotA {
276 expected: "enum",
277 actual: self.shape,
278 })
279 }
280 }
281
282 #[inline]
284 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
285 if let Def::Map(def) = self.shape.def {
286 Ok(PeekMap { value: self, def })
287 } else {
288 Err(ReflectError::WasNotA {
289 expected: "map",
290 actual: self.shape,
291 })
292 }
293 }
294
295 #[inline]
297 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
298 if let Def::Set(def) = self.shape.def {
299 Ok(PeekSet { value: self, def })
300 } else {
301 Err(ReflectError::WasNotA {
302 expected: "set",
303 actual: self.shape,
304 })
305 }
306 }
307
308 #[inline]
310 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
311 if let Def::List(def) = self.shape.def {
312 return Ok(PeekList { value: self, def });
313 }
314
315 Err(ReflectError::WasNotA {
316 expected: "list",
317 actual: self.shape,
318 })
319 }
320
321 #[inline]
323 pub fn into_ndarray(self) -> Result<PeekNdArray<'mem, 'facet>, ReflectError> {
324 if let Def::NdArray(def) = self.shape.def {
325 return Ok(PeekNdArray { value: self, def });
326 }
327
328 Err(ReflectError::WasNotA {
329 expected: "ndarray",
330 actual: self.shape,
331 })
332 }
333
334 #[inline]
336 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
337 match self.shape.def {
338 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
339 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
340 Def::Slice(def) => {
341 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
344 }
345 _ => {
346 match self.shape.ty {
348 Type::Pointer(ptr) => match ptr {
349 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
350 let target = vpt.target;
351 match target.def {
352 Def::Slice(def) => {
353 let ptr = unsafe { self.data.as_ptr::<*const [()]>() };
354 let ptr = PtrConst::new(unsafe {
355 NonNull::new_unchecked((*ptr) as *mut [()])
356 });
357 let peek = unsafe { Peek::unchecked_new(ptr, def.t) };
358
359 return Ok(PeekListLike::new(peek, ListLikeDef::Slice(def)));
360 }
361 _ => {
362 }
364 }
365 }
366 PointerType::Function(_) => {
367 }
369 },
370 _ => {
371 }
373 }
374
375 Err(ReflectError::WasNotA {
376 expected: "list, array or slice",
377 actual: self.shape,
378 })
379 }
380 }
381 }
382
383 #[inline]
385 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
386 if let Def::Pointer(def) = self.shape.def {
387 Ok(PeekPointer { value: self, def })
388 } else {
389 Err(ReflectError::WasNotA {
390 expected: "smart pointer",
391 actual: self.shape,
392 })
393 }
394 }
395
396 #[inline]
398 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
399 if let Def::Option(def) = self.shape.def {
400 Ok(PeekOption { value: self, def })
401 } else {
402 Err(ReflectError::WasNotA {
403 expected: "option",
404 actual: self.shape,
405 })
406 }
407 }
408
409 #[inline]
411 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
412 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
413 if struct_type.kind == StructKind::Tuple {
414 Ok(PeekTuple {
415 value: self,
416 ty: TupleType {
417 fields: struct_type.fields,
418 },
419 })
420 } else {
421 Err(ReflectError::WasNotA {
422 expected: "tuple",
423 actual: self.shape,
424 })
425 }
426 } else {
427 Err(ReflectError::WasNotA {
428 expected: "tuple",
429 actual: self.shape,
430 })
431 }
432 }
433
434 pub fn innermost_peek(self) -> Self {
440 let mut current_peek = self;
441 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
442 current_peek.shape.vtable.try_borrow_inner,
443 current_peek.shape.inner,
444 ) {
445 unsafe {
446 let inner_data = try_borrow_inner_fn(current_peek.data).unwrap_or_else(|e| {
447 panic!("innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}", current_peek.shape,
448 inner_shape)
449 });
450
451 current_peek = Peek {
452 data: inner_data,
453 shape: inner_shape,
454 invariant: PhantomData,
455 };
456 }
457 }
458 current_peek
459 }
460}
461
462impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
463 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
464 if let Some(display_fn) = self.vtable().display {
465 return unsafe { display_fn(self.data, f) };
466 }
467 write!(f, "⟨{}⟩", self.shape)
468 }
469}
470
471impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
472 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
473 if let Some(debug_fn) = self.vtable().debug {
474 return unsafe { debug_fn(self.data, f) };
475 }
476
477 write!(f, "⟨{}⟩", self.shape)
478 }
479}
480
481impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
482 #[inline]
483 fn eq(&self, other: &Self) -> bool {
484 self.partial_eq(other).unwrap_or(false)
485 }
486}
487
488impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
489 #[inline]
490 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
491 self.partial_cmp(other).unwrap_or(None)
492 }
493}
494
495impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
496 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
497 self.hash(hasher)
498 .expect("Hashing is not supported for this shape");
499 }
500}