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)]
42pub struct Peek<'mem, 'facet> {
43 pub(crate) data: GenericPtr<'mem>,
45
46 pub(crate) shape: &'static Shape,
48
49 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
50}
51
52impl<'mem, 'facet> Peek<'mem, 'facet> {
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(data: impl Into<GenericPtr<'mem>>, shape: &'static Shape) -> Self {
70 Self {
71 data: data.into(),
72 shape,
73 invariant: PhantomData,
74 }
75 }
76
77 #[inline(always)]
79 pub fn vtable(&self) -> &'static ValueVTable {
80 self.shape.vtable
81 }
82
83 #[inline]
85 pub fn id(&self) -> ValueId {
86 ValueId::new(self.shape, self.data.as_byte_ptr())
87 }
88
89 #[inline]
91 pub fn ptr_eq(&self, other: &Peek<'_, '_>) -> bool {
92 self.data.as_byte_ptr() == other.data.as_byte_ptr()
93 }
94
95 #[inline]
101 pub fn partial_eq(&self, other: &Peek<'_, '_>) -> Option<bool> {
102 match (self.data, other.data) {
103 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
104 (self.vtable().sized().unwrap().partial_eq)().map(|f| f(a, b))
105 },
106 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
107 (self.vtable().r#unsized().unwrap().partial_eq)().map(|f| f(a, b))
108 },
109 _ => None,
110 }
111 }
112
113 #[inline]
119 pub fn partial_cmp(&self, other: &Peek<'_, '_>) -> Option<Option<Ordering>> {
120 match (self.data, other.data) {
121 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
122 (self.vtable().sized().unwrap().partial_ord)().map(|f| f(a, b))
123 },
124 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
125 (self.vtable().r#unsized().unwrap().partial_ord)().map(|f| f(a, b))
126 },
127 _ => None,
128 }
129 }
130 #[inline(always)]
136 pub fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) -> Result<(), ReflectError> {
137 match self.data {
138 GenericPtr::Thin(ptr) => {
139 if let Some(hash_fn) = (self.vtable().sized().unwrap().hash)() {
140 let hasher_opaque = PtrMut::new(hasher);
141 unsafe {
142 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
143 opaque.as_mut::<H>().write(bytes)
144 })
145 };
146 return Ok(());
147 }
148 }
149 GenericPtr::Wide(ptr) => {
150 if let Some(hash_fn) = (self.vtable().r#unsized().unwrap().hash)() {
151 let hasher_opaque = PtrMut::new(hasher);
152 unsafe {
153 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
154 opaque.as_mut::<H>().write(bytes)
155 })
156 };
157 return Ok(());
158 }
159 }
160 }
161 Err(ReflectError::OperationFailed {
162 shape: self.shape(),
163 operation: "hash",
164 })
165 }
166
167 #[inline(always)]
178 pub fn type_name(
179 &self,
180 f: &mut core::fmt::Formatter<'_>,
181 opts: TypeNameOpts,
182 ) -> core::fmt::Result {
183 (self.shape.vtable.type_name())(f, opts)
184 }
185
186 #[inline(always)]
188 pub const fn shape(&self) -> &'static Shape {
189 self.shape
190 }
191
192 #[inline(always)]
194 pub const fn data(&self) -> GenericPtr<'mem> {
195 self.data
196 }
197
198 #[inline]
200 pub fn scalar_type(&self) -> Option<ScalarType> {
201 ScalarType::try_from_shape(self.shape)
202 }
203
204 #[inline]
210 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&T, ReflectError> {
211 if self.shape != T::SHAPE {
212 Err(ReflectError::WrongShape {
213 expected: self.shape,
214 actual: T::SHAPE,
215 })
216 } else {
217 Ok(unsafe { self.data.get::<T>() })
218 }
219 }
220
221 pub fn as_str(&self) -> Option<&'mem str> {
224 let peek = self.innermost_peek();
225 if let Some(ScalarType::Str) = peek.scalar_type() {
226 unsafe { Some(peek.data.get::<&str>()) }
227 } else if let Some(ScalarType::String) = peek.scalar_type() {
228 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
229 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
230 let target_shape = (vpt.target)();
231 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
232 unsafe { Some(peek.data.get::<&str>()) }
233 } else {
234 None
235 }
236 } else {
237 None
238 }
239 }
240
241 #[inline]
244 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
245 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
247 let target_shape = (vpt.target)();
248 if let Def::Slice(sd) = target_shape.def {
249 if sd.t().is_type::<u8>() {
250 unsafe { return Some(self.data.get::<&[u8]>()) }
251 }
252 }
253 }
254 None
255 }
256
257 #[inline]
259 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
260 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
261 Ok(PeekStruct { value: self, ty })
262 } else {
263 Err(ReflectError::WasNotA {
264 expected: "struct",
265 actual: self.shape,
266 })
267 }
268 }
269
270 #[inline]
272 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
273 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
274 Ok(PeekEnum { value: self, ty })
275 } else {
276 Err(ReflectError::WasNotA {
277 expected: "enum",
278 actual: self.shape,
279 })
280 }
281 }
282
283 #[inline]
285 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
286 if let Def::Map(def) = self.shape.def {
287 Ok(PeekMap { value: self, def })
288 } else {
289 Err(ReflectError::WasNotA {
290 expected: "map",
291 actual: self.shape,
292 })
293 }
294 }
295
296 #[inline]
298 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
299 if let Def::Set(def) = self.shape.def {
300 Ok(PeekSet { value: self, def })
301 } else {
302 Err(ReflectError::WasNotA {
303 expected: "set",
304 actual: self.shape,
305 })
306 }
307 }
308
309 #[inline]
311 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
312 if let Def::List(def) = self.shape.def {
313 return Ok(PeekList { value: self, def });
314 }
315
316 Err(ReflectError::WasNotA {
317 expected: "list",
318 actual: self.shape,
319 })
320 }
321
322 #[inline]
324 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
325 match self.shape.def {
326 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
327 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
328 Def::Slice(def) => {
329 if matches!(self.data, GenericPtr::Wide(_)) {
332 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
333 } else {
334 Err(ReflectError::WasNotA {
335 expected: "slice with wide pointer",
336 actual: self.shape,
337 })
338 }
339 }
340 _ => {
341 match self.shape.ty {
343 Type::Pointer(ptr) => match ptr {
344 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
345 let target = (vpt.target)();
346 match target.def {
347 Def::Slice(def) => {
348 return Ok(PeekListLike::new(self, ListLikeDef::Slice(def)));
349 }
350 _ => {
351 }
353 }
354 }
355 PointerType::Function(_) => {
356 }
358 },
359 _ => {
360 }
362 }
363
364 Err(ReflectError::WasNotA {
365 expected: "list, array or slice",
366 actual: self.shape,
367 })
368 }
369 }
370 }
371
372 #[inline]
374 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
375 if let Def::Pointer(def) = self.shape.def {
376 Ok(PeekPointer { value: self, def })
377 } else {
378 Err(ReflectError::WasNotA {
379 expected: "smart pointer",
380 actual: self.shape,
381 })
382 }
383 }
384
385 #[inline]
387 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
388 if let Def::Option(def) = self.shape.def {
389 Ok(PeekOption { value: self, def })
390 } else {
391 Err(ReflectError::WasNotA {
392 expected: "option",
393 actual: self.shape,
394 })
395 }
396 }
397
398 #[inline]
400 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
401 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
402 if struct_type.kind == StructKind::Tuple {
403 Ok(PeekTuple {
404 value: self,
405 ty: TupleType {
406 fields: struct_type.fields,
407 },
408 })
409 } else {
410 Err(ReflectError::WasNotA {
411 expected: "tuple",
412 actual: self.shape,
413 })
414 }
415 } else {
416 Err(ReflectError::WasNotA {
417 expected: "tuple",
418 actual: self.shape,
419 })
420 }
421 }
422
423 pub fn innermost_peek(self) -> Self {
429 let mut current_peek = self;
430 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
431 current_peek
432 .shape
433 .vtable
434 .sized()
435 .and_then(|v| (v.try_borrow_inner)()),
436 current_peek.shape.inner,
437 ) {
438 unsafe {
439 let inner_data = try_borrow_inner_fn(current_peek.data.thin().unwrap()).unwrap_or_else(|e| {
440 panic!("innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}", current_peek.shape,
441 inner_shape())
442 });
443
444 current_peek = Peek {
445 data: inner_data.into(),
446 shape: inner_shape(),
447 invariant: PhantomData,
448 };
449 }
450 }
451 current_peek
452 }
453}
454
455impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
456 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
457 match self.data {
458 GenericPtr::Thin(ptr) => {
459 if let Some(display_fn) = (self.vtable().sized().unwrap().display)() {
460 return unsafe { display_fn(ptr, f) };
461 }
462 }
463 GenericPtr::Wide(ptr) => {
464 if let Some(display_fn) = (self.vtable().r#unsized().unwrap().display)() {
465 return unsafe { display_fn(ptr, f) };
466 }
467 }
468 }
469 write!(f, "⟨{}⟩", self.shape)
470 }
471}
472
473impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
474 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
475 match self.data {
476 GenericPtr::Thin(ptr) => {
477 if let Some(debug_fn) = (self.vtable().sized().unwrap().debug)() {
478 return unsafe { debug_fn(ptr, f) };
479 }
480 }
481 GenericPtr::Wide(ptr) => {
482 if let Some(debug_fn) = (self.vtable().r#unsized().unwrap().debug)() {
483 return unsafe { debug_fn(ptr, f) };
484 }
485 }
486 }
487 write!(f, "⟨{}⟩", self.shape)
488 }
489}
490
491impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
492 #[inline]
493 fn eq(&self, other: &Self) -> bool {
494 self.partial_eq(other).unwrap_or(false)
495 }
496}
497
498impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
499 #[inline]
500 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
501 self.partial_cmp(other).unwrap_or(None)
502 }
503}
504
505impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
506 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
507 self.hash(hasher)
508 .expect("Hashing is not supported for this shape");
509 }
510}