1use core::{cmp::Ordering, marker::PhantomData};
2use facet_core::{
3 Def, Facet, GenericPtr, PointerType, PtrMut, Shape, StructKind, Type, TypeNameOpts, UserType,
4 ValueVTable,
5};
6
7use crate::{PeekSet, ReflectError, ScalarType};
8
9use super::{
10 ListLikeDef, PeekEnum, PeekList, PeekListLike, PeekMap, PeekOption, PeekPointer, PeekStruct,
11 PeekTuple, tuple::TupleType,
12};
13
14#[derive(Clone, Copy, PartialEq, Eq, Hash)]
16pub struct ValueId {
17 pub(crate) shape: &'static Shape,
18 pub(crate) ptr: *const u8,
19}
20
21impl ValueId {
22 #[inline]
23 pub(crate) fn new(shape: &'static Shape, ptr: *const u8) -> Self {
24 Self { shape, ptr }
25 }
26}
27
28impl core::fmt::Display for ValueId {
29 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
30 write!(f, "{}@{:p}", self.shape, self.ptr)
31 }
32}
33
34impl core::fmt::Debug for ValueId {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 core::fmt::Display::fmt(self, f)
37 }
38}
39
40#[derive(Clone, Copy)]
46pub struct Peek<'mem, 'facet> {
47 pub(crate) data: GenericPtr<'mem>,
49
50 pub(crate) shape: &'static Shape,
52
53 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
54}
55
56impl<'mem, 'facet> Peek<'mem, 'facet> {
57 pub fn new<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Self {
59 Self {
60 data: GenericPtr::new(t),
61 shape: T::SHAPE,
62 invariant: PhantomData,
63 }
64 }
65
66 pub unsafe fn unchecked_new(data: impl Into<GenericPtr<'mem>>, shape: &'static Shape) -> Self {
75 Self {
76 data: data.into(),
77 shape,
78 invariant: PhantomData,
79 }
80 }
81
82 #[inline(always)]
84 pub fn vtable(&self) -> &'static ValueVTable {
85 self.shape.vtable
86 }
87
88 #[inline]
90 pub fn id(&self) -> ValueId {
91 ValueId::new(self.shape, self.data.as_byte_ptr())
92 }
93
94 #[inline]
96 pub fn ptr_eq(&self, other: &Peek<'_, '_>) -> bool {
97 self.data.as_byte_ptr() == other.data.as_byte_ptr()
98 }
99
100 #[inline]
106 pub fn partial_eq(&self, other: &Peek<'_, '_>) -> Option<bool> {
107 match (self.data, other.data) {
108 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
109 (self.vtable().sized().unwrap().partial_eq)().map(|f| f(a, b))
110 },
111 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
112 (self.vtable().r#unsized().unwrap().partial_eq)().map(|f| f(a, b))
113 },
114 _ => None,
115 }
116 }
117
118 #[inline]
124 pub fn partial_cmp(&self, other: &Peek<'_, '_>) -> Option<Option<Ordering>> {
125 match (self.data, other.data) {
126 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
127 (self.vtable().sized().unwrap().partial_ord)().map(|f| f(a, b))
128 },
129 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
130 (self.vtable().r#unsized().unwrap().partial_ord)().map(|f| f(a, b))
131 },
132 _ => None,
133 }
134 }
135 #[inline(always)]
141 pub fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) -> Result<(), ReflectError> {
142 match self.data {
143 GenericPtr::Thin(ptr) => {
144 if let Some(hash_fn) = (self.vtable().sized().unwrap().hash)() {
145 let hasher_opaque = PtrMut::new(hasher);
146 unsafe {
147 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
148 opaque.as_mut::<H>().write(bytes)
149 })
150 };
151 return Ok(());
152 }
153 }
154 GenericPtr::Wide(ptr) => {
155 if let Some(hash_fn) = (self.vtable().r#unsized().unwrap().hash)() {
156 let hasher_opaque = PtrMut::new(hasher);
157 unsafe {
158 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
159 opaque.as_mut::<H>().write(bytes)
160 })
161 };
162 return Ok(());
163 }
164 }
165 }
166 Err(ReflectError::OperationFailed {
167 shape: self.shape(),
168 operation: "hash",
169 })
170 }
171
172 #[inline(always)]
183 pub fn type_name(
184 &self,
185 f: &mut core::fmt::Formatter<'_>,
186 opts: TypeNameOpts,
187 ) -> core::fmt::Result {
188 (self.shape.vtable.type_name())(f, opts)
189 }
190
191 #[inline(always)]
193 pub const fn shape(&self) -> &'static Shape {
194 self.shape
195 }
196
197 #[inline(always)]
199 pub const fn data(&self) -> GenericPtr<'mem> {
200 self.data
201 }
202
203 #[inline]
205 pub fn scalar_type(&self) -> Option<ScalarType> {
206 ScalarType::try_from_shape(self.shape)
207 }
208
209 #[inline]
215 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&T, ReflectError> {
216 if self.shape != T::SHAPE {
217 Err(ReflectError::WrongShape {
218 expected: self.shape,
219 actual: T::SHAPE,
220 })
221 } else {
222 Ok(unsafe { self.data.get::<T>() })
223 }
224 }
225
226 pub fn as_str(&self) -> Option<&'mem str> {
229 let peek = self.innermost_peek();
230 if let Some(ScalarType::Str) = peek.scalar_type() {
231 unsafe { Some(peek.data.get::<&str>()) }
232 } else if let Some(ScalarType::String) = peek.scalar_type() {
233 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
234 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
235 let target_shape = (vpt.target)();
236 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
237 unsafe { Some(peek.data.get::<&str>()) }
238 } else {
239 None
240 }
241 } else {
242 None
243 }
244 }
245
246 #[inline]
249 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
250 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
252 let target_shape = (vpt.target)();
253 if let Def::Slice(sd) = target_shape.def {
254 if sd.t().is_type::<u8>() {
255 unsafe { return Some(self.data.get::<&[u8]>()) }
256 }
257 }
258 }
259 None
260 }
261
262 #[inline]
264 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
265 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
266 Ok(PeekStruct { value: self, ty })
267 } else {
268 Err(ReflectError::WasNotA {
269 expected: "struct",
270 actual: self.shape,
271 })
272 }
273 }
274
275 #[inline]
277 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
278 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
279 Ok(PeekEnum { value: self, ty })
280 } else {
281 Err(ReflectError::WasNotA {
282 expected: "enum",
283 actual: self.shape,
284 })
285 }
286 }
287
288 #[inline]
290 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
291 if let Def::Map(def) = self.shape.def {
292 Ok(PeekMap { value: self, def })
293 } else {
294 Err(ReflectError::WasNotA {
295 expected: "map",
296 actual: self.shape,
297 })
298 }
299 }
300
301 #[inline]
303 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
304 if let Def::Set(def) = self.shape.def {
305 Ok(PeekSet { value: self, def })
306 } else {
307 Err(ReflectError::WasNotA {
308 expected: "set",
309 actual: self.shape,
310 })
311 }
312 }
313
314 #[inline]
316 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
317 if let Def::List(def) = self.shape.def {
318 return Ok(PeekList { value: self, def });
319 }
320
321 Err(ReflectError::WasNotA {
322 expected: "list",
323 actual: self.shape,
324 })
325 }
326
327 #[inline]
329 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
330 match self.shape.def {
331 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
332 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
333 Def::Slice(def) => {
334 if matches!(self.data, GenericPtr::Wide(_)) {
337 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
338 } else {
339 Err(ReflectError::WasNotA {
340 expected: "slice with wide pointer",
341 actual: self.shape,
342 })
343 }
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 return Ok(PeekListLike::new(self, ListLikeDef::Slice(def)));
354 }
355 _ => {
356 }
358 }
359 }
360 PointerType::Function(_) => {
361 }
363 },
364 _ => {
365 }
367 }
368
369 Err(ReflectError::WasNotA {
370 expected: "list, array or slice",
371 actual: self.shape,
372 })
373 }
374 }
375 }
376
377 #[inline]
379 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
380 if let Def::Pointer(def) = self.shape.def {
381 Ok(PeekPointer { value: self, def })
382 } else {
383 Err(ReflectError::WasNotA {
384 expected: "smart pointer",
385 actual: self.shape,
386 })
387 }
388 }
389
390 #[inline]
392 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
393 if let Def::Option(def) = self.shape.def {
394 Ok(PeekOption { value: self, def })
395 } else {
396 Err(ReflectError::WasNotA {
397 expected: "option",
398 actual: self.shape,
399 })
400 }
401 }
402
403 #[inline]
405 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
406 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
407 if struct_type.kind == StructKind::Tuple {
408 Ok(PeekTuple {
409 value: self,
410 ty: TupleType {
411 fields: struct_type.fields,
412 },
413 })
414 } else {
415 Err(ReflectError::WasNotA {
416 expected: "tuple",
417 actual: self.shape,
418 })
419 }
420 } else {
421 Err(ReflectError::WasNotA {
422 expected: "tuple",
423 actual: self.shape,
424 })
425 }
426 }
427
428 pub fn innermost_peek(self) -> Self {
434 let mut current_peek = self;
435 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
436 current_peek
437 .shape
438 .vtable
439 .sized()
440 .and_then(|v| (v.try_borrow_inner)()),
441 current_peek.shape.inner,
442 ) {
443 unsafe {
444 let inner_data = try_borrow_inner_fn(current_peek.data.thin().unwrap()).unwrap_or_else(|e| {
445 panic!("innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}", current_peek.shape,
446 inner_shape())
447 });
448
449 current_peek = Peek {
450 data: inner_data.into(),
451 shape: inner_shape(),
452 invariant: PhantomData,
453 };
454 }
455 }
456 current_peek
457 }
458}
459
460impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
461 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
462 match self.data {
463 GenericPtr::Thin(ptr) => {
464 if let Some(display_fn) = (self.vtable().sized().unwrap().display)() {
465 return unsafe { display_fn(ptr, f) };
466 }
467 }
468 GenericPtr::Wide(ptr) => {
469 if let Some(display_fn) = (self.vtable().r#unsized().unwrap().display)() {
470 return unsafe { display_fn(ptr, f) };
471 }
472 }
473 }
474 write!(f, "⟨{}⟩", self.shape)
475 }
476}
477
478impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
479 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
480 match self.data {
481 GenericPtr::Thin(ptr) => {
482 if let Some(debug_fn) = (self.vtable().sized().unwrap().debug)() {
483 return unsafe { debug_fn(ptr, f) };
484 }
485 }
486 GenericPtr::Wide(ptr) => {
487 if let Some(debug_fn) = (self.vtable().r#unsized().unwrap().debug)() {
488 return unsafe { debug_fn(ptr, f) };
489 }
490 }
491 }
492 write!(f, "⟨{}⟩", self.shape)
493 }
494}
495
496impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
497 #[inline]
498 fn eq(&self, other: &Self) -> bool {
499 self.partial_eq(other).unwrap_or(false)
500 }
501}
502
503impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
504 #[inline]
505 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
506 self.partial_cmp(other).unwrap_or(None)
507 }
508}
509
510impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
511 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
512 self.hash(hasher)
513 .expect("Hashing is not supported for this shape");
514 }
515}