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, PeekPointer, PeekStruct, PeekTuple,
11 tuple::TupleType,
12};
13
14#[derive(Clone, Copy, PartialEq, Eq, Hash)]
16pub struct ValueId<'shape> {
17 pub(crate) shape: &'shape Shape<'shape>,
18 pub(crate) ptr: *const u8,
19}
20
21impl<'shape> ValueId<'shape> {
22 #[inline]
23 pub(crate) fn new(shape: &'shape Shape<'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)]
42pub struct Peek<'mem, 'facet, 'shape> {
43 pub(crate) data: GenericPtr<'mem>,
45
46 pub(crate) shape: &'shape Shape<'shape>,
48
49 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
50}
51
52impl<'mem, 'facet, 'shape> Peek<'mem, 'facet, 'shape> {
53 pub fn new<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Self {
55 Self {
56 data: GenericPtr::new(t),
57 shape: T::SHAPE,
58 invariant: PhantomData,
59 }
60 }
61
62 pub unsafe fn unchecked_new(
70 data: impl Into<GenericPtr<'mem>>,
71 shape: &'shape Shape<'shape>,
72 ) -> Self {
73 Self {
74 data: data.into(),
75 shape,
76 invariant: PhantomData,
77 }
78 }
79
80 #[inline(always)]
82 pub fn vtable(&self) -> &'shape ValueVTable {
83 self.shape.vtable
84 }
85
86 #[inline]
88 pub fn id(&self) -> ValueId<'shape> {
89 ValueId::new(self.shape, self.data.as_byte_ptr())
90 }
91
92 #[inline]
94 pub fn ptr_eq(&self, other: &Peek<'_, '_, '_>) -> bool {
95 self.data.as_byte_ptr() == other.data.as_byte_ptr()
96 }
97
98 #[inline]
104 pub fn partial_eq(&self, other: &Peek<'_, '_, '_>) -> Option<bool> {
105 match (self.data, other.data) {
106 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
107 (self.vtable().sized().unwrap().partial_eq)().map(|f| f(a, b))
108 },
109 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
110 (self.vtable().r#unsized().unwrap().partial_eq)().map(|f| f(a, b))
111 },
112 _ => None,
113 }
114 }
115
116 #[inline]
122 pub fn partial_cmp(&self, other: &Peek<'_, '_, '_>) -> Option<Option<Ordering>> {
123 match (self.data, other.data) {
124 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
125 (self.vtable().sized().unwrap().partial_ord)().map(|f| f(a, b))
126 },
127 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
128 (self.vtable().r#unsized().unwrap().partial_ord)().map(|f| f(a, b))
129 },
130 _ => None,
131 }
132 }
133 #[inline(always)]
139 pub fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) -> Result<(), ReflectError<'_>> {
140 match self.data {
141 GenericPtr::Thin(ptr) => {
142 if let Some(hash_fn) = (self.vtable().sized().unwrap().hash)() {
143 let hasher_opaque = PtrMut::new(hasher);
144 unsafe {
145 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
146 opaque.as_mut::<H>().write(bytes)
147 })
148 };
149 return Ok(());
150 }
151 }
152 GenericPtr::Wide(ptr) => {
153 if let Some(hash_fn) = (self.vtable().r#unsized().unwrap().hash)() {
154 let hasher_opaque = PtrMut::new(hasher);
155 unsafe {
156 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
157 opaque.as_mut::<H>().write(bytes)
158 })
159 };
160 return Ok(());
161 }
162 }
163 }
164 Err(ReflectError::OperationFailed {
165 shape: self.shape(),
166 operation: "hash",
167 })
168 }
169
170 #[inline(always)]
181 pub fn type_name(
182 &self,
183 f: &mut core::fmt::Formatter<'_>,
184 opts: TypeNameOpts,
185 ) -> core::fmt::Result {
186 (self.shape.vtable.type_name())(f, opts)
187 }
188
189 #[inline(always)]
191 pub const fn shape(&self) -> &'shape Shape<'shape> {
192 self.shape
193 }
194
195 #[inline(always)]
197 pub const fn data(&self) -> GenericPtr<'mem> {
198 self.data
199 }
200
201 #[inline]
203 pub fn scalar_type(&self) -> Option<ScalarType> {
204 ScalarType::try_from_shape(self.shape)
205 }
206
207 #[inline]
213 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&T, ReflectError<'shape>> {
214 if self.shape != T::SHAPE {
215 Err(ReflectError::WrongShape {
216 expected: self.shape,
217 actual: T::SHAPE,
218 })
219 } else {
220 Ok(unsafe { self.data.get::<T>() })
221 }
222 }
223
224 pub fn as_str(&self) -> Option<&'mem str> {
227 let peek = self.innermost_peek();
228 if let Some(ScalarType::Str) = peek.scalar_type() {
229 unsafe { Some(peek.data.get::<&str>()) }
230 } else if let Some(ScalarType::String) = peek.scalar_type() {
231 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
232 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
233 let target_shape = (vpt.target)();
234 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
235 unsafe { Some(peek.data.get::<&str>()) }
236 } else {
237 None
238 }
239 } else {
240 None
241 }
242 }
243
244 #[inline]
247 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
248 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
250 let target_shape = (vpt.target)();
251 if let Def::Slice(sd) = target_shape.def {
252 if sd.t().is_type::<u8>() {
253 unsafe { return Some(self.data.get::<&[u8]>()) }
254 }
255 }
256 }
257 None
258 }
259
260 #[inline]
262 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet, 'shape>, ReflectError<'shape>> {
263 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
264 Ok(PeekStruct { value: self, ty })
265 } else {
266 Err(ReflectError::WasNotA {
267 expected: "struct",
268 actual: self.shape,
269 })
270 }
271 }
272
273 #[inline]
275 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet, 'shape>, ReflectError<'shape>> {
276 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
277 Ok(PeekEnum { value: self, ty })
278 } else {
279 Err(ReflectError::WasNotA {
280 expected: "enum",
281 actual: self.shape,
282 })
283 }
284 }
285
286 #[inline]
288 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet, 'shape>, ReflectError<'shape>> {
289 if let Def::Map(def) = self.shape.def {
290 Ok(PeekMap { value: self, def })
291 } else {
292 Err(ReflectError::WasNotA {
293 expected: "map",
294 actual: self.shape,
295 })
296 }
297 }
298
299 #[inline]
301 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet, 'shape>, ReflectError<'shape>> {
302 if let Def::Set(def) = self.shape.def {
303 Ok(PeekSet { value: self, def })
304 } else {
305 Err(ReflectError::WasNotA {
306 expected: "set",
307 actual: self.shape,
308 })
309 }
310 }
311
312 #[inline]
314 pub fn into_list(self) -> Result<PeekList<'mem, 'facet, 'shape>, ReflectError<'shape>> {
315 if let Def::List(def) = self.shape.def {
316 return Ok(PeekList { value: self, def });
317 }
318
319 Err(ReflectError::WasNotA {
320 expected: "list",
321 actual: self.shape,
322 })
323 }
324
325 #[inline]
327 pub fn into_list_like(
328 self,
329 ) -> Result<PeekListLike<'mem, 'facet, 'shape>, ReflectError<'shape>> {
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, 'shape>, ReflectError<'shape>> {
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(
393 self,
394 ) -> Result<super::PeekOption<'mem, 'facet, 'shape>, ReflectError<'shape>> {
395 if let Def::Option(def) = self.shape.def {
396 Ok(super::PeekOption { value: self, def })
397 } else {
398 Err(ReflectError::WasNotA {
399 expected: "option",
400 actual: self.shape,
401 })
402 }
403 }
404
405 #[inline]
407 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet, 'shape>, ReflectError<'shape>> {
408 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
409 if struct_type.kind == StructKind::Tuple {
410 Ok(PeekTuple {
411 value: self,
412 ty: TupleType {
413 fields: struct_type.fields,
414 },
415 })
416 } else {
417 Err(ReflectError::WasNotA {
418 expected: "tuple",
419 actual: self.shape,
420 })
421 }
422 } else {
423 Err(ReflectError::WasNotA {
424 expected: "tuple",
425 actual: self.shape,
426 })
427 }
428 }
429
430 pub fn innermost_peek(self) -> Self {
436 let mut current_peek = self;
437 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
438 current_peek
439 .shape
440 .vtable
441 .sized()
442 .and_then(|v| (v.try_borrow_inner)()),
443 current_peek.shape.inner,
444 ) {
445 unsafe {
446 let inner_data = try_borrow_inner_fn(current_peek.data.thin().unwrap()).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.into(),
453 shape: inner_shape(),
454 invariant: PhantomData,
455 };
456 }
457 }
458 current_peek
459 }
460}
461
462impl<'mem, 'facet, 'shape> core::fmt::Display for Peek<'mem, 'facet, 'shape> {
463 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
464 match self.data {
465 GenericPtr::Thin(ptr) => {
466 if let Some(display_fn) = (self.vtable().sized().unwrap().display)() {
467 return unsafe { display_fn(ptr, f) };
468 }
469 }
470 GenericPtr::Wide(ptr) => {
471 if let Some(display_fn) = (self.vtable().r#unsized().unwrap().display)() {
472 return unsafe { display_fn(ptr, f) };
473 }
474 }
475 }
476 write!(f, "⟨{}⟩", self.shape)
477 }
478}
479
480impl<'mem, 'facet, 'shape> core::fmt::Debug for Peek<'mem, 'facet, 'shape> {
481 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
482 match self.data {
483 GenericPtr::Thin(ptr) => {
484 if let Some(debug_fn) = (self.vtable().sized().unwrap().debug)() {
485 return unsafe { debug_fn(ptr, f) };
486 }
487 }
488 GenericPtr::Wide(ptr) => {
489 if let Some(debug_fn) = (self.vtable().r#unsized().unwrap().debug)() {
490 return unsafe { debug_fn(ptr, f) };
491 }
492 }
493 }
494 write!(f, "⟨{}⟩", self.shape)
495 }
496}
497
498impl<'mem, 'facet, 'shape> core::cmp::PartialEq for Peek<'mem, 'facet, 'shape> {
499 #[inline]
500 fn eq(&self, other: &Self) -> bool {
501 self.partial_eq(other).unwrap_or(false)
502 }
503}
504
505impl<'mem, 'facet, 'shape> core::cmp::PartialOrd for Peek<'mem, 'facet, 'shape> {
506 #[inline]
507 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
508 self.partial_cmp(other).unwrap_or(None)
509 }
510}
511
512impl<'mem, 'facet, 'shape> core::hash::Hash for Peek<'mem, 'facet, 'shape> {
513 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
514 self.hash(hasher)
515 .expect("Hashing is not supported for this shape");
516 }
517}