facet_core/types/
value.rs

1use crate::{
2    TypedPtrUninit,
3    ptr::{PtrConst, PtrMut, PtrUninit},
4};
5use bitflags::bitflags;
6use core::{cmp::Ordering, marker::PhantomData, mem};
7
8use crate::Shape;
9
10use super::UnsizedError;
11
12//======== Type Information ========
13
14/// A function that formats the name of a type.
15///
16/// This helps avoid allocations, and it takes options.
17pub type TypeNameFn = fn(f: &mut core::fmt::Formatter, opts: TypeNameOpts) -> core::fmt::Result;
18
19/// Options for formatting the name of a type
20#[non_exhaustive]
21#[derive(Clone, Copy)]
22pub struct TypeNameOpts {
23    /// as long as this is > 0, keep formatting the type parameters
24    /// when it reaches 0, format type parameters as `...`
25    /// if negative, all type parameters are formatted
26    pub recurse_ttl: isize,
27}
28
29impl Default for TypeNameOpts {
30    fn default() -> Self {
31        Self { recurse_ttl: -1 }
32    }
33}
34
35impl TypeNameOpts {
36    /// Create a new `NameOpts` for which none of the type parameters are formatted
37    pub fn none() -> Self {
38        Self { recurse_ttl: 0 }
39    }
40
41    /// Create a new `NameOpts` for which only the direct children are formatted
42    pub fn one() -> Self {
43        Self { recurse_ttl: 1 }
44    }
45
46    /// Create a new `NameOpts` for which all type parameters are formatted
47    pub fn infinite() -> Self {
48        Self { recurse_ttl: -1 }
49    }
50
51    /// Decrease the `recurse_ttl` — if it's != 0, returns options to pass when
52    /// formatting children type parameters.
53    ///
54    /// If this returns `None` and you have type parameters, you should render a
55    /// `…` (unicode ellipsis) character instead of your list of types.
56    ///
57    /// See the implementation for `Vec` for examples.
58    pub fn for_children(&self) -> Option<Self> {
59        match self.recurse_ttl.cmp(&0) {
60            Ordering::Greater => Some(Self {
61                recurse_ttl: self.recurse_ttl - 1,
62            }),
63            Ordering::Less => Some(Self {
64                recurse_ttl: self.recurse_ttl,
65            }),
66            Ordering::Equal => None,
67        }
68    }
69}
70
71//======== Invariants ========
72
73/// Function to validate the invariants of a value. If it returns false, the value is considered invalid.
74///
75/// # Safety
76///
77/// The `value` parameter must point to aligned, initialized memory of the correct type.
78pub type InvariantsFn = for<'mem> unsafe fn(value: PtrConst<'mem>) -> bool;
79/// Function to validate the invariants of a value. If it returns false, the value is considered invalid.
80pub type InvariantsFnTyped<T> = fn(value: &T) -> bool;
81
82//======== Memory Management ========
83
84/// Function to drop a value
85///
86/// # Safety
87///
88/// The `value` parameter must point to aligned, initialized memory of the correct type.
89/// After calling this function, the memory pointed to by `value` should not be accessed again
90/// until it is properly reinitialized.
91pub type DropInPlaceFn = for<'mem> unsafe fn(value: PtrMut<'mem>) -> PtrUninit<'mem>;
92
93/// Function to clone a value into another already-allocated value
94///
95/// # Safety
96///
97/// The `source` parameter must point to aligned, initialized memory of the correct type.
98/// The `target` parameter has the correct layout and alignment, but points to
99/// uninitialized memory. The function returns the same pointer wrapped in an [`PtrMut`].
100pub type CloneIntoFn =
101    for<'src, 'dst> unsafe fn(source: PtrConst<'src>, target: PtrUninit<'dst>) -> PtrMut<'dst>;
102/// Function to clone a value into another already-allocated value
103pub type CloneIntoFnTyped<T> =
104    for<'src, 'dst> fn(source: &'src T, target: TypedPtrUninit<'dst, T>) -> &'dst mut T;
105
106/// Function to set a value to its default in-place
107///
108/// # Safety
109///
110/// The `target` parameter has the correct layout and alignment, but points to
111/// uninitialized memory. The function returns the same pointer wrapped in an [`PtrMut`].
112pub type DefaultInPlaceFn = for<'mem> unsafe fn(target: PtrUninit<'mem>) -> PtrMut<'mem>;
113/// Function to set a value to its default in-place
114pub type DefaultInPlaceFnTyped<T> = for<'mem> fn(target: TypedPtrUninit<'mem, T>) -> &'mem mut T;
115
116//======== Conversion ========
117
118/// Function to parse a value from a string.
119///
120/// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.
121///
122/// # Safety
123///
124/// The `target` parameter has the correct layout and alignment, but points to
125/// uninitialized memory. If this function succeeds, it should return `Ok` with the
126/// same pointer wrapped in an [`PtrMut`]. If parsing fails, it returns `Err` with an error.
127pub type ParseFn =
128    for<'mem> unsafe fn(s: &str, target: PtrUninit<'mem>) -> Result<PtrMut<'mem>, ParseError>;
129/// Function to parse a value from a string.
130///
131/// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.
132pub type ParseFnTyped<T> =
133    for<'mem> fn(s: &str, target: TypedPtrUninit<'mem, T>) -> Result<&'mem mut T, ParseError>;
134
135/// Error returned by [`ParseFn`]
136#[non_exhaustive]
137#[derive(Debug)]
138pub enum ParseError {
139    /// Generic error message
140    Generic(&'static str),
141}
142
143impl core::fmt::Display for ParseError {
144    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
145        match self {
146            ParseError::Generic(msg) => write!(f, "Parse failed: {}", msg),
147        }
148    }
149}
150
151impl core::error::Error for ParseError {}
152
153/// Function to try converting from another type
154///
155/// # Safety
156///
157/// The `target` parameter has the correct layout and alignment, but points to
158/// uninitialized memory. If this function succeeds, it should return `Ok` with the
159/// same pointer wrapped in an [`PtrMut`]. If conversion fails, it returns `Err` with an error.
160pub type TryFromFn = for<'src, 'mem> unsafe fn(
161    source: PtrConst<'src>,
162    source_shape: &'static Shape,
163    target: PtrUninit<'mem>,
164) -> Result<PtrMut<'mem>, TryFromError>;
165/// Function to try converting from another type
166pub type TryFromFnTyped<T> = for<'src, 'mem> fn(
167    source: &'src T,
168    source_shape: &'static Shape,
169    target: TypedPtrUninit<'mem, T>,
170) -> Result<&'mem mut T, TryFromError>;
171
172/// Error type for TryFrom conversion failures
173#[non_exhaustive]
174#[derive(Debug, PartialEq, Clone)]
175pub enum TryFromError {
176    /// Generic conversion error
177    Generic(&'static str),
178    /// The target shape doesn't implement conversion from any source shape (no try_from in vtable)
179    Unimplemented,
180    /// The target shape has a conversion implementation, but it doesn't support converting from this specific source shape
181    UnsupportedSourceShape {
182        /// The source shape that failed to convert
183        src_shape: &'static Shape,
184
185        /// The shapes that the `TryFrom` implementation supports
186        expected: &'static [&'static Shape],
187    },
188    /// `!Sized` type
189    Unsized,
190}
191
192impl core::fmt::Display for TryFromError {
193    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
194        match self {
195            TryFromError::Generic(msg) => write!(f, "{}", msg),
196            TryFromError::Unimplemented => write!(
197                f,
198                "Shape doesn't implement any conversions (no try_from function)",
199            ),
200            TryFromError::UnsupportedSourceShape {
201                src_shape: source_shape,
202                expected,
203            } => {
204                write!(f, "Incompatible types: {} (expected one of ", source_shape)?;
205                for (index, sh) in expected.iter().enumerate() {
206                    if index > 0 {
207                        write!(f, ", ")?;
208                    }
209                    write!(f, "{}", sh)?;
210                }
211                write!(f, ")")?;
212                Ok(())
213            }
214            TryFromError::Unsized => write!(f, "Unsized type"),
215        }
216    }
217}
218
219impl core::error::Error for TryFromError {}
220
221impl From<UnsizedError> for TryFromError {
222    fn from(_value: UnsizedError) -> Self {
223        Self::Unsized
224    }
225}
226
227/// Function to convert a transparent/newtype wrapper into its inner type.
228///
229/// This is used for types that wrap another type (like smart pointers, newtypes, etc.)
230/// where the wrapper can be unwrapped to access the inner value. Primarily used during serialization.
231///
232/// # Safety
233///
234/// This function is unsafe because it operates on raw pointers.
235///
236/// The `src_ptr` must point to a valid, initialized instance of the wrapper type.
237/// The `dst` pointer must point to valid, uninitialized memory suitable for holding an instance
238/// of the inner type.
239///
240/// The function will return a pointer to the initialized inner value.
241pub type TryIntoInnerFn = for<'src, 'dst> unsafe fn(
242    src_ptr: PtrConst<'src>,
243    dst: PtrUninit<'dst>,
244) -> Result<PtrMut<'dst>, TryIntoInnerError>;
245/// Function to convert a transparent/newtype wrapper into its inner type.
246///
247/// This is used for types that wrap another type (like smart pointers, newtypes, etc.)
248/// where the wrapper can be unwrapped to access the inner value. Primarily used during serialization.
249pub type TryIntoInnerFnTyped<T> = for<'src, 'dst> fn(
250    src_ptr: &'src T,
251    dst: TypedPtrUninit<'dst, T>,
252) -> Result<&'dst mut T, TryIntoInnerError>;
253
254/// Error type returned by [`TryIntoInnerFn`] when attempting to extract
255/// the inner value from a wrapper type.
256#[non_exhaustive]
257#[derive(Debug, Clone, PartialEq, Eq)]
258pub enum TryIntoInnerError {
259    /// Indicates that the inner value cannot be extracted at this time,
260    /// such as when a mutable borrow is already active.
261    Unavailable,
262    /// Indicates that another unspecified error occurred during extraction.
263    Other(&'static str),
264}
265
266impl core::fmt::Display for TryIntoInnerError {
267    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
268        match self {
269            TryIntoInnerError::Unavailable => {
270                write!(f, "inner value is unavailable for extraction")
271            }
272            TryIntoInnerError::Other(msg) => write!(f, "{}", msg),
273        }
274    }
275}
276
277impl core::error::Error for TryIntoInnerError {}
278
279/// Function to borrow the inner value from a transparent/newtype wrapper without copying.
280///
281/// This is used for types that wrap another type (like smart pointers, newtypes, etc.)
282/// to efficiently access the inner value without transferring ownership.
283///
284/// # Safety
285///
286/// This function is unsafe because it operates on raw pointers.
287///
288/// The `src_ptr` must point to a valid, initialized instance of the wrapper type.
289/// The returned pointer points to memory owned by the wrapper and remains valid
290/// as long as the wrapper is valid and not mutated.
291pub type TryBorrowInnerFn =
292    for<'src> unsafe fn(src_ptr: PtrConst<'src>) -> Result<PtrConst<'src>, TryBorrowInnerError>;
293/// Function to borrow the inner value from a transparent/newtype wrapper without copying.
294///
295/// This is used for types that wrap another type (like smart pointers, newtypes, etc.)
296/// to efficiently access the inner value without transferring ownership.
297pub type TryBorrowInnerFnTyped<T> =
298    for<'src> fn(src_ptr: &'src T) -> Result<&'src T, TryBorrowInnerError>;
299
300/// Error type returned by [`TryBorrowInnerFn`] when attempting to borrow
301/// the inner value from a wrapper type.
302#[non_exhaustive]
303#[derive(Debug, Clone, PartialEq, Eq)]
304pub enum TryBorrowInnerError {
305    /// Indicates that the inner value cannot be borrowed at this time,
306    /// such as when a mutable borrow is already active.
307    Unavailable,
308    /// Indicates an other, unspecified error occurred during the borrow attempt.
309    /// The contained string provides a description of the error.
310    Other(&'static str),
311}
312
313impl core::fmt::Display for TryBorrowInnerError {
314    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
315        match self {
316            TryBorrowInnerError::Unavailable => {
317                write!(f, "inner value is unavailable for borrowing")
318            }
319            TryBorrowInnerError::Other(msg) => {
320                write!(f, "{}", msg)
321            }
322        }
323    }
324}
325
326impl core::error::Error for TryBorrowInnerError {}
327
328//======== Comparison ========
329
330/// Function to check if two values are partially equal
331///
332/// # Safety
333///
334/// Both `left` and `right` parameters must point to aligned, initialized memory of the correct type.
335pub type PartialEqFn = for<'l, 'r> unsafe fn(left: PtrConst<'l>, right: PtrConst<'r>) -> bool;
336/// Function to check if two values are partially equal
337pub type PartialEqFnTyped<T> = fn(left: &T, right: &T) -> bool;
338
339/// Function to compare two values and return their ordering if comparable
340///
341/// # Safety
342///
343/// Both `left` and `right` parameters must point to aligned, initialized memory of the correct type.
344pub type PartialOrdFn =
345    for<'l, 'r> unsafe fn(left: PtrConst<'l>, right: PtrConst<'r>) -> Option<Ordering>;
346/// Function to compare two values and return their ordering if comparable
347pub type PartialOrdFnTyped<T> = fn(left: &T, right: &T) -> Option<Ordering>;
348
349/// Function to compare two values and return their ordering
350///
351/// # Safety
352///
353/// Both `left` and `right` parameters must point to aligned, initialized memory of the correct type.
354pub type CmpFn = for<'l, 'r> unsafe fn(left: PtrConst<'l>, right: PtrConst<'r>) -> Ordering;
355/// Function to compare two values and return their ordering
356pub type CmpFnTyped<T> = fn(left: &T, right: &T) -> Ordering;
357
358//======== Hashing ========
359
360/// Function to hash a value
361///
362/// # Safety
363///
364/// The `value` parameter must point to aligned, initialized memory of the correct type.
365/// The hasher pointer must be a valid pointer to a Hasher trait object.
366pub type HashFn = for<'mem> unsafe fn(
367    value: PtrConst<'mem>,
368    hasher_this: PtrMut<'mem>,
369    hasher_write_fn: HasherWriteFn,
370);
371/// Function to hash a value
372pub type HashFnTyped<T> =
373    for<'mem> fn(value: &'mem T, hasher_this: PtrMut<'mem>, hasher_write_fn: HasherWriteFn);
374
375/// Function to write bytes to a hasher
376///
377/// # Safety
378///
379/// The `hasher_self` parameter must be a valid pointer to a hasher
380pub type HasherWriteFn = for<'mem> unsafe fn(hasher_self: PtrMut<'mem>, bytes: &[u8]);
381/// Function to write bytes to a hasher
382pub type HasherWriteFnTyped<T> = for<'mem> fn(hasher_self: &'mem mut T, bytes: &[u8]);
383
384/// Provides an implementation of [`core::hash::Hasher`] for a given hasher pointer and write function
385///
386/// See [`HashFn`] for more details on the parameters.
387pub struct HasherProxy<'a> {
388    hasher_this: PtrMut<'a>,
389    hasher_write_fn: HasherWriteFn,
390}
391
392impl<'a> HasherProxy<'a> {
393    /// Create a new `HasherProxy` from a hasher pointer and a write function
394    ///
395    /// # Safety
396    ///
397    /// The `hasher_this` parameter must be a valid pointer to a Hasher trait object.
398    /// The `hasher_write_fn` parameter must be a valid function pointer.
399    pub unsafe fn new(hasher_this: PtrMut<'a>, hasher_write_fn: HasherWriteFn) -> Self {
400        Self {
401            hasher_this,
402            hasher_write_fn,
403        }
404    }
405}
406
407impl core::hash::Hasher for HasherProxy<'_> {
408    fn finish(&self) -> u64 {
409        unimplemented!("finish is not needed for this implementation")
410    }
411    fn write(&mut self, bytes: &[u8]) {
412        unsafe { (self.hasher_write_fn)(self.hasher_this, bytes) }
413    }
414}
415
416//======== Marker Traits ========
417
418bitflags! {
419    /// Bitflags for common marker traits that a type may implement
420    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
421    pub struct MarkerTraits: u8 {
422        /// Indicates that the type implements the [`Eq`] marker trait
423        const EQ = 1 << 0;
424        /// Indicates that the type implements the [`Send`] marker trait
425        const SEND = 1 << 1;
426        /// Indicates that the type implements the [`Sync`] marker trait
427        const SYNC = 1 << 2;
428        /// Indicates that the type implements the [`Copy`] marker trait
429        const COPY = 1 << 3;
430        /// Indicates that the type implements the [`Unpin`] marker trait
431        const UNPIN = 1 << 4;
432    }
433}
434
435//======== Display and Debug ========
436
437/// Function to format a value for display
438///
439/// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.
440///
441/// # Safety
442///
443/// The `value` parameter must point to aligned, initialized memory of the correct type.
444pub type DisplayFn =
445    for<'mem> unsafe fn(value: PtrConst<'mem>, f: &mut core::fmt::Formatter) -> core::fmt::Result;
446/// Function to format a value for display
447///
448/// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.
449pub type DisplayFnTyped<T> = fn(value: &T, f: &mut core::fmt::Formatter) -> core::fmt::Result;
450
451/// Function to format a value for debug.
452/// If this returns None, the shape did not implement Debug.
453pub type DebugFn =
454    for<'mem> unsafe fn(value: PtrConst<'mem>, f: &mut core::fmt::Formatter) -> core::fmt::Result;
455/// Function to format a value for debug.
456/// If this returns None, the shape did not implement Debug.
457pub type DebugFnTyped<T> = fn(value: &T, f: &mut core::fmt::Formatter) -> core::fmt::Result;
458
459/// VTable for common operations that can be performed on any shape
460#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
461#[repr(C)]
462#[non_exhaustive]
463pub struct ValueVTable {
464    /// cf. [`TypeNameFn`]
465    pub type_name: TypeNameFn,
466    /// Marker traits implemented by the type
467    // FIXME: move out of vtable, it's not really... functions.
468    // Belongs in Shape directly.
469    pub marker_traits: MarkerTraits,
470
471    /// cf. [`DropInPlaceFn`] — if None, drops without side-effects
472    pub drop_in_place: Option<DropInPlaceFn>,
473
474    /// cf. [`InvariantsFn`]
475    pub invariants: Option<InvariantsFn>,
476
477    /// cf. [`DisplayFn`]
478    pub display: Option<DisplayFn>,
479
480    /// cf. [`DebugFn`]
481    pub debug: Option<DebugFn>,
482
483    /// cf. [`DefaultInPlaceFn`]
484    pub default_in_place: Option<DefaultInPlaceFn>,
485
486    /// cf. [`CloneIntoFn`]
487    pub clone_into: Option<CloneIntoFn>,
488
489    /// cf. [`PartialEqFn`] for equality comparison
490    pub eq: Option<PartialEqFn>,
491
492    /// cf. [`PartialOrdFn`] for partial ordering comparison
493    pub partial_ord: Option<PartialOrdFn>,
494
495    /// cf. [`CmpFn`] for total ordering
496    pub ord: Option<CmpFn>,
497
498    /// cf. [`HashFn`]
499    pub hash: Option<HashFn>,
500
501    /// cf. [`ParseFn`]
502    pub parse: Option<ParseFn>,
503
504    /// cf. [`TryFromFn`]
505    ///
506    /// This also acts as a "TryFromInner" — you can use it to go:
507    ///
508    ///   * `String` => `Utf8PathBuf`
509    ///   * `String` => `Uuid`
510    ///   * `T` => `Option<T>`
511    ///   * `T` => `Arc<T>`
512    ///   * `T` => `NonZero<T>`
513    ///   * etc.
514    ///
515    pub try_from: Option<TryFromFn>,
516
517    /// cf. [`TryIntoInnerFn`]
518    ///
519    /// This is used by transparent types to convert the wrapper type into its inner value.
520    /// Primarily used during serialization.
521    pub try_into_inner: Option<TryIntoInnerFn>,
522
523    /// cf. [`TryBorrowInnerFn`]
524    ///
525    /// This is used by transparent types to efficiently access the inner value without copying.
526    pub try_borrow_inner: Option<TryBorrowInnerFn>,
527}
528
529impl ValueVTable {
530    /// Check if the type implements the [`Eq`] marker trait
531    pub fn is_eq(&self) -> bool {
532        self.marker_traits.contains(MarkerTraits::EQ)
533    }
534
535    /// Check if the type implements the [`Send`] marker trait
536    pub fn is_send(&self) -> bool {
537        self.marker_traits.contains(MarkerTraits::SEND)
538    }
539
540    /// Check if the type implements the [`Sync`] marker trait
541    pub fn is_sync(&self) -> bool {
542        self.marker_traits.contains(MarkerTraits::SYNC)
543    }
544
545    /// Check if the type implements the [`Copy`] marker trait
546    pub fn is_copy(&self) -> bool {
547        self.marker_traits.contains(MarkerTraits::COPY)
548    }
549
550    /// Check if the type implements the [`Unpin`] marker trait
551    pub fn is_unpin(&self) -> bool {
552        self.marker_traits.contains(MarkerTraits::UNPIN)
553    }
554
555    /// Creates a new [`ValueVTableBuilder`]
556    pub const fn builder<T>() -> ValueVTableBuilder<T> {
557        ValueVTableBuilder::new()
558    }
559}
560
561/// A typed view of a [`ValueVTable`].
562#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
563pub struct VTableView<T>(&'static ValueVTable, PhantomData<T>);
564
565impl<'a, T: crate::Facet<'a> + ?Sized> VTableView<&'a mut T> {
566    /// Fetches the vtable for the type.
567    pub fn of_deref() -> Self {
568        Self(T::SHAPE.vtable, PhantomData)
569    }
570}
571
572impl<'a, T: crate::Facet<'a> + ?Sized> VTableView<&'a T> {
573    /// Fetches the vtable for the type.
574    pub fn of_deref() -> Self {
575        Self(T::SHAPE.vtable, PhantomData)
576    }
577}
578
579impl<'a, T: crate::Facet<'a>> VTableView<T> {
580    /// Fetches the vtable for the type.
581    pub fn of() -> Self {
582        Self(T::SHAPE.vtable, PhantomData)
583    }
584
585    /// cf. [`TypeNameFn`]
586    #[inline(always)]
587    pub fn type_name(self) -> TypeNameFn {
588        self.0.type_name
589    }
590
591    /// cf. [`InvariantsFn`]
592    #[inline(always)]
593    pub fn invariants(self) -> Option<InvariantsFnTyped<T>> {
594        self.0.invariants.map(|invariants| unsafe {
595            mem::transmute::<InvariantsFn, InvariantsFnTyped<T>>(invariants)
596        })
597    }
598
599    /// cf. [`DisplayFn`]
600    #[inline(always)]
601    pub fn display(self) -> Option<DisplayFnTyped<T>> {
602        self.0
603            .display
604            .map(|display| unsafe { mem::transmute::<DisplayFn, DisplayFnTyped<T>>(display) })
605    }
606
607    /// cf. [`DebugFn`]
608    #[inline(always)]
609    pub fn debug(self) -> Option<DebugFnTyped<T>> {
610        self.0
611            .debug
612            .map(|debug| unsafe { mem::transmute::<DebugFn, DebugFnTyped<T>>(debug) })
613    }
614
615    /// cf. [`DefaultInPlaceFn`]
616    #[inline(always)]
617    pub fn default_in_place(self) -> Option<DefaultInPlaceFnTyped<T>> {
618        self.0.default_in_place.map(|default_in_place| unsafe {
619            mem::transmute::<DefaultInPlaceFn, DefaultInPlaceFnTyped<T>>(default_in_place)
620        })
621    }
622
623    /// cf. [`CloneIntoFn`]
624    #[inline(always)]
625    pub fn clone_into(self) -> Option<CloneIntoFnTyped<T>> {
626        self.0.clone_into.map(|clone_into| unsafe {
627            mem::transmute::<CloneIntoFn, CloneIntoFnTyped<T>>(clone_into)
628        })
629    }
630
631    /// cf. [`PartialEqFn`] for equality comparison
632    #[inline(always)]
633    pub fn eq(self) -> Option<PartialEqFnTyped<T>> {
634        self.0
635            .eq
636            .map(|eq| unsafe { mem::transmute::<PartialEqFn, PartialEqFnTyped<T>>(eq) })
637    }
638
639    /// cf. [`PartialOrdFn`] for partial ordering comparison
640    #[inline(always)]
641    pub fn partial_ord(self) -> Option<PartialOrdFnTyped<T>> {
642        self.0.partial_ord.map(|partial_ord| unsafe {
643            mem::transmute::<PartialOrdFn, PartialOrdFnTyped<T>>(partial_ord)
644        })
645    }
646
647    /// cf. [`CmpFn`] for total ordering
648    #[inline(always)]
649    pub fn ord(self) -> Option<CmpFnTyped<T>> {
650        self.0
651            .ord
652            .map(|ord| unsafe { mem::transmute::<CmpFn, CmpFnTyped<T>>(ord) })
653    }
654
655    /// cf. [`HashFn`]
656    #[inline(always)]
657    pub fn hash(self) -> Option<HashFnTyped<T>> {
658        self.0
659            .hash
660            .map(|hash| unsafe { mem::transmute::<HashFn, HashFnTyped<T>>(hash) })
661    }
662
663    /// cf. [`ParseFn`]
664    #[inline(always)]
665    pub fn parse(self) -> Option<ParseFnTyped<T>> {
666        self.0
667            .parse
668            .map(|parse| unsafe { mem::transmute::<ParseFn, ParseFnTyped<T>>(parse) })
669    }
670
671    /// cf. [`TryFromFn`]
672    ///
673    /// This also acts as a "TryFromInner" — you can use it to go:
674    ///
675    ///   * `String` => `Utf8PathBuf`
676    ///   * `String` => `Uuid`
677    ///   * `T` => `Option<T>`
678    ///   * `T` => `Arc<T>`
679    ///   * `T` => `NonZero<T>`
680    ///   * etc.
681    ///
682    #[inline(always)]
683    pub fn try_from(self) -> Option<TryFromFnTyped<T>> {
684        self.0
685            .try_from
686            .map(|try_from| unsafe { mem::transmute::<TryFromFn, TryFromFnTyped<T>>(try_from) })
687    }
688
689    /// cf. [`TryIntoInnerFn`]
690    ///
691    /// This is used by transparent types to convert the wrapper type into its inner value.
692    /// Primarily used during serialization.
693    #[inline(always)]
694    pub fn try_into_inner(self) -> Option<TryIntoInnerFnTyped<T>> {
695        self.0.try_into_inner.map(|try_into_inner| unsafe {
696            mem::transmute::<TryIntoInnerFn, TryIntoInnerFnTyped<T>>(try_into_inner)
697        })
698    }
699
700    /// cf. [`TryBorrowInnerFn`]
701    ///
702    /// This is used by transparent types to efficiently access the inner value without copying.
703    #[inline(always)]
704    pub fn try_borrow_inner(self) -> Option<TryBorrowInnerFnTyped<T>> {
705        self.0.try_borrow_inner.map(|try_borrow_inner| unsafe {
706            mem::transmute::<TryBorrowInnerFn, TryBorrowInnerFnTyped<T>>(try_borrow_inner)
707        })
708    }
709}
710
711/// Builds a [`ValueVTable`]
712pub struct ValueVTableBuilder<T> {
713    type_name: Option<TypeNameFn>,
714    display: Option<DisplayFnTyped<T>>,
715    debug: Option<DebugFnTyped<T>>,
716    default_in_place: Option<DefaultInPlaceFnTyped<T>>,
717    clone_into: Option<CloneIntoFnTyped<T>>,
718    marker_traits: MarkerTraits,
719    eq: Option<PartialEqFnTyped<T>>,
720    partial_ord: Option<PartialOrdFnTyped<T>>,
721    ord: Option<CmpFnTyped<T>>,
722    hash: Option<HashFnTyped<T>>,
723    drop_in_place: Option<DropInPlaceFn>,
724    invariants: Option<InvariantsFnTyped<T>>,
725    parse: Option<ParseFnTyped<T>>,
726    try_from: Option<TryFromFnTyped<T>>,
727    try_into_inner: Option<TryIntoInnerFnTyped<T>>,
728    try_borrow_inner: Option<TryBorrowInnerFnTyped<T>>,
729    _pd: PhantomData<T>,
730}
731
732impl<T> ValueVTableBuilder<T> {
733    /// Creates a new [`ValueVTableBuilder`] with all fields set to `None`.
734    #[allow(clippy::new_without_default)]
735    pub const fn new() -> Self {
736        Self {
737            type_name: None,
738            display: None,
739            debug: None,
740            default_in_place: None,
741            clone_into: None,
742            marker_traits: MarkerTraits::empty(),
743            eq: None,
744            partial_ord: None,
745            ord: None,
746            hash: None,
747            drop_in_place: None,
748            invariants: None,
749            parse: None,
750            try_from: None,
751            try_into_inner: None,
752            try_borrow_inner: None,
753            _pd: PhantomData,
754        }
755    }
756
757    /// Sets the type name function for this builder.
758    pub const fn type_name(mut self, type_name: TypeNameFn) -> Self {
759        self.type_name = Some(type_name);
760        self
761    }
762
763    /// Sets the display function for this builder.
764    pub const fn display(mut self, display: DisplayFnTyped<T>) -> Self {
765        self.display = Some(display);
766        self
767    }
768
769    /// Sets the display function for this builder if Some.
770    pub const fn display_maybe(mut self, display: Option<DisplayFnTyped<T>>) -> Self {
771        self.display = display;
772        self
773    }
774
775    /// Sets the debug function for this builder.
776    pub const fn debug(mut self, debug: DebugFnTyped<T>) -> Self {
777        self.debug = Some(debug);
778        self
779    }
780
781    /// Sets the debug function for this builder if Some.
782    pub const fn debug_maybe(mut self, debug: Option<DebugFnTyped<T>>) -> Self {
783        self.debug = debug;
784        self
785    }
786
787    /// Sets the default_in_place function for this builder.
788    pub const fn default_in_place(mut self, default_in_place: DefaultInPlaceFnTyped<T>) -> Self {
789        self.default_in_place = Some(default_in_place);
790        self
791    }
792
793    /// Sets the default_in_place function for this builder if Some.
794    pub const fn default_in_place_maybe(
795        mut self,
796        default_in_place: Option<DefaultInPlaceFnTyped<T>>,
797    ) -> Self {
798        self.default_in_place = default_in_place;
799        self
800    }
801
802    /// Sets the clone_into function for this builder.
803    pub const fn clone_into(mut self, clone_into: CloneIntoFnTyped<T>) -> Self {
804        self.clone_into = Some(clone_into);
805        self
806    }
807
808    /// Sets the clone_into function for this builder if Some.
809    pub const fn clone_into_maybe(mut self, clone_into: Option<CloneIntoFnTyped<T>>) -> Self {
810        self.clone_into = clone_into;
811        self
812    }
813
814    /// Sets the marker traits for this builder.
815    pub const fn marker_traits(mut self, marker_traits: MarkerTraits) -> Self {
816        self.marker_traits = marker_traits;
817        self
818    }
819
820    /// Sets the eq function for this builder.
821    pub const fn eq(mut self, eq: PartialEqFnTyped<T>) -> Self {
822        self.eq = Some(eq);
823        self
824    }
825
826    /// Sets the eq function for this builder if Some.
827    pub const fn eq_maybe(mut self, eq: Option<PartialEqFnTyped<T>>) -> Self {
828        self.eq = eq;
829        self
830    }
831
832    /// Sets the partial_ord function for this builder.
833    pub const fn partial_ord(mut self, partial_ord: PartialOrdFnTyped<T>) -> Self {
834        self.partial_ord = Some(partial_ord);
835        self
836    }
837
838    /// Sets the partial_ord function for this builder if Some.
839    pub const fn partial_ord_maybe(mut self, partial_ord: Option<PartialOrdFnTyped<T>>) -> Self {
840        self.partial_ord = partial_ord;
841        self
842    }
843
844    /// Sets the ord function for this builder.
845    pub const fn ord(mut self, ord: CmpFnTyped<T>) -> Self {
846        self.ord = Some(ord);
847        self
848    }
849
850    /// Sets the ord function for this builder if Some.
851    pub const fn ord_maybe(mut self, ord: Option<CmpFnTyped<T>>) -> Self {
852        self.ord = ord;
853        self
854    }
855
856    /// Sets the hash function for this builder.
857    pub const fn hash(mut self, hash: HashFnTyped<T>) -> Self {
858        self.hash = Some(hash);
859        self
860    }
861
862    /// Sets the hash function for this builder if Some.
863    pub const fn hash_maybe(mut self, hash: Option<HashFnTyped<T>>) -> Self {
864        self.hash = hash;
865        self
866    }
867
868    /// Overwrites the drop_in_place function for this builder.
869    ///
870    /// This is usually not necessary, the builder builder will default this to the appropriate type.
871    pub const fn drop_in_place(mut self, drop_in_place: DropInPlaceFn) -> Self {
872        self.drop_in_place = Some(drop_in_place);
873        self
874    }
875
876    /// Sets the invariants function for this builder.
877    pub const fn invariants(mut self, invariants: InvariantsFnTyped<T>) -> Self {
878        self.invariants = Some(invariants);
879        self
880    }
881
882    /// Sets the parse function for this builder.
883    pub const fn parse(mut self, parse: ParseFnTyped<T>) -> Self {
884        self.parse = Some(parse);
885        self
886    }
887
888    /// Sets the parse function for this builder if Some.
889    pub const fn parse_maybe(mut self, parse: Option<ParseFnTyped<T>>) -> Self {
890        self.parse = parse;
891        self
892    }
893
894    /// Sets the try_from function for this builder.
895    pub const fn try_from(mut self, try_from: TryFromFnTyped<T>) -> Self {
896        self.try_from = Some(try_from);
897        self
898    }
899
900    /// Sets the try_into_inner function for this builder.
901    pub const fn try_into_inner(mut self, try_into_inner: TryIntoInnerFnTyped<T>) -> Self {
902        self.try_into_inner = Some(try_into_inner);
903        self
904    }
905
906    /// Sets the borrow_inner function for this builder.
907    pub const fn try_borrow_inner(mut self, try_borrow_inner: TryBorrowInnerFnTyped<T>) -> Self {
908        self.try_borrow_inner = Some(try_borrow_inner);
909        self
910    }
911
912    /// Builds the [`ValueVTable`] from the current state of the builder.
913    pub const fn build(self) -> ValueVTable {
914        ValueVTable {
915            type_name: self.type_name.unwrap(),
916            marker_traits: self.marker_traits,
917            invariants: unsafe {
918                mem::transmute::<Option<InvariantsFnTyped<T>>, Option<InvariantsFn>>(
919                    self.invariants,
920                )
921            },
922            display: unsafe {
923                mem::transmute::<Option<DisplayFnTyped<T>>, Option<DisplayFn>>(self.display)
924            },
925            debug: unsafe {
926                mem::transmute::<Option<DebugFnTyped<T>>, Option<DebugFn>>(self.debug)
927            },
928            default_in_place: unsafe {
929                mem::transmute::<Option<DefaultInPlaceFnTyped<T>>, Option<DefaultInPlaceFn>>(
930                    self.default_in_place,
931                )
932            },
933            clone_into: unsafe {
934                mem::transmute::<Option<CloneIntoFnTyped<T>>, Option<CloneIntoFn>>(self.clone_into)
935            },
936            eq: unsafe {
937                mem::transmute::<Option<PartialEqFnTyped<T>>, Option<PartialEqFn>>(self.eq)
938            },
939            partial_ord: unsafe {
940                mem::transmute::<Option<PartialOrdFnTyped<T>>, Option<PartialOrdFn>>(
941                    self.partial_ord,
942                )
943            },
944            ord: unsafe { mem::transmute::<Option<CmpFnTyped<T>>, Option<CmpFn>>(self.ord) },
945            hash: unsafe { mem::transmute::<Option<HashFnTyped<T>>, Option<HashFn>>(self.hash) },
946            parse: unsafe {
947                mem::transmute::<Option<ParseFnTyped<T>>, Option<ParseFn>>(self.parse)
948            },
949            try_from: unsafe {
950                mem::transmute::<Option<TryFromFnTyped<T>>, Option<TryFromFn>>(self.try_from)
951            },
952            try_into_inner: unsafe {
953                mem::transmute::<Option<TryIntoInnerFnTyped<T>>, Option<TryIntoInnerFn>>(
954                    self.try_into_inner,
955                )
956            },
957            try_borrow_inner: unsafe {
958                mem::transmute::<Option<TryBorrowInnerFnTyped<T>>, Option<TryBorrowInnerFn>>(
959                    self.try_borrow_inner,
960                )
961            },
962            drop_in_place: if let Some(drop_in_place) = self.drop_in_place {
963                Some(drop_in_place)
964            } else if mem::needs_drop::<T>() {
965                Some(|value| unsafe { value.drop_in_place::<T>() })
966            } else {
967                None
968            },
969        }
970    }
971}