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>> VTableView<T> {
566    /// Fetches the vtable for the type.
567    pub fn of() -> Self {
568        Self(T::SHAPE.vtable, PhantomData)
569    }
570
571    /// cf. [`TypeNameFn`]
572    #[inline(always)]
573    pub fn type_name(self) -> TypeNameFn {
574        self.0.type_name
575    }
576
577    /// cf. [`InvariantsFn`]
578    #[inline(always)]
579    pub fn invariants(self) -> Option<InvariantsFnTyped<T>> {
580        self.0.invariants.map(|invariants| unsafe {
581            mem::transmute::<InvariantsFn, InvariantsFnTyped<T>>(invariants)
582        })
583    }
584
585    /// cf. [`DisplayFn`]
586    #[inline(always)]
587    pub fn display(self) -> Option<DisplayFnTyped<T>> {
588        self.0
589            .display
590            .map(|display| unsafe { mem::transmute::<DisplayFn, DisplayFnTyped<T>>(display) })
591    }
592
593    /// cf. [`DebugFn`]
594    #[inline(always)]
595    pub fn debug(self) -> Option<DebugFnTyped<T>> {
596        self.0
597            .debug
598            .map(|debug| unsafe { mem::transmute::<DebugFn, DebugFnTyped<T>>(debug) })
599    }
600
601    /// cf. [`DefaultInPlaceFn`]
602    #[inline(always)]
603    pub fn default_in_place(self) -> Option<DefaultInPlaceFnTyped<T>> {
604        self.0.default_in_place.map(|default_in_place| unsafe {
605            mem::transmute::<DefaultInPlaceFn, DefaultInPlaceFnTyped<T>>(default_in_place)
606        })
607    }
608
609    /// cf. [`CloneIntoFn`]
610    #[inline(always)]
611    pub fn clone_into(self) -> Option<CloneIntoFnTyped<T>> {
612        self.0.clone_into.map(|clone_into| unsafe {
613            mem::transmute::<CloneIntoFn, CloneIntoFnTyped<T>>(clone_into)
614        })
615    }
616
617    /// cf. [`PartialEqFn`] for equality comparison
618    #[inline(always)]
619    pub fn eq(self) -> Option<PartialEqFnTyped<T>> {
620        self.0
621            .eq
622            .map(|eq| unsafe { mem::transmute::<PartialEqFn, PartialEqFnTyped<T>>(eq) })
623    }
624
625    /// cf. [`PartialOrdFn`] for partial ordering comparison
626    #[inline(always)]
627    pub fn partial_ord(self) -> Option<PartialOrdFnTyped<T>> {
628        self.0.partial_ord.map(|partial_ord| unsafe {
629            mem::transmute::<PartialOrdFn, PartialOrdFnTyped<T>>(partial_ord)
630        })
631    }
632
633    /// cf. [`CmpFn`] for total ordering
634    #[inline(always)]
635    pub fn ord(self) -> Option<CmpFnTyped<T>> {
636        self.0
637            .ord
638            .map(|ord| unsafe { mem::transmute::<CmpFn, CmpFnTyped<T>>(ord) })
639    }
640
641    /// cf. [`HashFn`]
642    #[inline(always)]
643    pub fn hash(self) -> Option<HashFnTyped<T>> {
644        self.0
645            .hash
646            .map(|hash| unsafe { mem::transmute::<HashFn, HashFnTyped<T>>(hash) })
647    }
648
649    /// cf. [`ParseFn`]
650    #[inline(always)]
651    pub fn parse(self) -> Option<ParseFnTyped<T>> {
652        self.0
653            .parse
654            .map(|parse| unsafe { mem::transmute::<ParseFn, ParseFnTyped<T>>(parse) })
655    }
656
657    /// cf. [`TryFromFn`]
658    ///
659    /// This also acts as a "TryFromInner" — you can use it to go:
660    ///
661    ///   * `String` => `Utf8PathBuf`
662    ///   * `String` => `Uuid`
663    ///   * `T` => `Option<T>`
664    ///   * `T` => `Arc<T>`
665    ///   * `T` => `NonZero<T>`
666    ///   * etc.
667    ///
668    #[inline(always)]
669    pub fn try_from(self) -> Option<TryFromFnTyped<T>> {
670        self.0
671            .try_from
672            .map(|try_from| unsafe { mem::transmute::<TryFromFn, TryFromFnTyped<T>>(try_from) })
673    }
674
675    /// cf. [`TryIntoInnerFn`]
676    ///
677    /// This is used by transparent types to convert the wrapper type into its inner value.
678    /// Primarily used during serialization.
679    #[inline(always)]
680    pub fn try_into_inner(self) -> Option<TryIntoInnerFnTyped<T>> {
681        self.0.try_into_inner.map(|try_into_inner| unsafe {
682            mem::transmute::<TryIntoInnerFn, TryIntoInnerFnTyped<T>>(try_into_inner)
683        })
684    }
685
686    /// cf. [`TryBorrowInnerFn`]
687    ///
688    /// This is used by transparent types to efficiently access the inner value without copying.
689    #[inline(always)]
690    pub fn try_borrow_inner(self) -> Option<TryBorrowInnerFnTyped<T>> {
691        self.0.try_borrow_inner.map(|try_borrow_inner| unsafe {
692            mem::transmute::<TryBorrowInnerFn, TryBorrowInnerFnTyped<T>>(try_borrow_inner)
693        })
694    }
695}
696
697/// Builds a [`ValueVTable`]
698pub struct ValueVTableBuilder<T> {
699    type_name: Option<TypeNameFn>,
700    display: Option<DisplayFnTyped<T>>,
701    debug: Option<DebugFnTyped<T>>,
702    default_in_place: Option<DefaultInPlaceFnTyped<T>>,
703    clone_into: Option<CloneIntoFnTyped<T>>,
704    marker_traits: MarkerTraits,
705    eq: Option<PartialEqFnTyped<T>>,
706    partial_ord: Option<PartialOrdFnTyped<T>>,
707    ord: Option<CmpFnTyped<T>>,
708    hash: Option<HashFnTyped<T>>,
709    drop_in_place: Option<DropInPlaceFn>,
710    invariants: Option<InvariantsFnTyped<T>>,
711    parse: Option<ParseFnTyped<T>>,
712    try_from: Option<TryFromFnTyped<T>>,
713    try_into_inner: Option<TryIntoInnerFnTyped<T>>,
714    try_borrow_inner: Option<TryBorrowInnerFnTyped<T>>,
715    _pd: PhantomData<T>,
716}
717
718impl<T> ValueVTableBuilder<T> {
719    /// Creates a new [`ValueVTableBuilder`] with all fields set to `None`.
720    #[allow(clippy::new_without_default)]
721    pub const fn new() -> Self {
722        Self {
723            type_name: None,
724            display: None,
725            debug: None,
726            default_in_place: None,
727            clone_into: None,
728            marker_traits: MarkerTraits::empty(),
729            eq: None,
730            partial_ord: None,
731            ord: None,
732            hash: None,
733            drop_in_place: None,
734            invariants: None,
735            parse: None,
736            try_from: None,
737            try_into_inner: None,
738            try_borrow_inner: None,
739            _pd: PhantomData,
740        }
741    }
742
743    /// Sets the type name function for this builder.
744    pub const fn type_name(mut self, type_name: TypeNameFn) -> Self {
745        self.type_name = Some(type_name);
746        self
747    }
748
749    /// Sets the display function for this builder.
750    pub const fn display(mut self, display: DisplayFnTyped<T>) -> Self {
751        self.display = Some(display);
752        self
753    }
754
755    /// Sets the display function for this builder if Some.
756    pub const fn display_maybe(mut self, display: Option<DisplayFnTyped<T>>) -> Self {
757        self.display = display;
758        self
759    }
760
761    /// Sets the debug function for this builder.
762    pub const fn debug(mut self, debug: DebugFnTyped<T>) -> Self {
763        self.debug = Some(debug);
764        self
765    }
766
767    /// Sets the debug function for this builder if Some.
768    pub const fn debug_maybe(mut self, debug: Option<DebugFnTyped<T>>) -> Self {
769        self.debug = debug;
770        self
771    }
772
773    /// Sets the default_in_place function for this builder.
774    pub const fn default_in_place(mut self, default_in_place: DefaultInPlaceFnTyped<T>) -> Self {
775        self.default_in_place = Some(default_in_place);
776        self
777    }
778
779    /// Sets the default_in_place function for this builder if Some.
780    pub const fn default_in_place_maybe(
781        mut self,
782        default_in_place: Option<DefaultInPlaceFnTyped<T>>,
783    ) -> Self {
784        self.default_in_place = default_in_place;
785        self
786    }
787
788    /// Sets the clone_into function for this builder.
789    pub const fn clone_into(mut self, clone_into: CloneIntoFnTyped<T>) -> Self {
790        self.clone_into = Some(clone_into);
791        self
792    }
793
794    /// Sets the clone_into function for this builder if Some.
795    pub const fn clone_into_maybe(mut self, clone_into: Option<CloneIntoFnTyped<T>>) -> Self {
796        self.clone_into = clone_into;
797        self
798    }
799
800    /// Sets the marker traits for this builder.
801    pub const fn marker_traits(mut self, marker_traits: MarkerTraits) -> Self {
802        self.marker_traits = marker_traits;
803        self
804    }
805
806    /// Sets the eq function for this builder.
807    pub const fn eq(mut self, eq: PartialEqFnTyped<T>) -> Self {
808        self.eq = Some(eq);
809        self
810    }
811
812    /// Sets the eq function for this builder if Some.
813    pub const fn eq_maybe(mut self, eq: Option<PartialEqFnTyped<T>>) -> Self {
814        self.eq = eq;
815        self
816    }
817
818    /// Sets the partial_ord function for this builder.
819    pub const fn partial_ord(mut self, partial_ord: PartialOrdFnTyped<T>) -> Self {
820        self.partial_ord = Some(partial_ord);
821        self
822    }
823
824    /// Sets the partial_ord function for this builder if Some.
825    pub const fn partial_ord_maybe(mut self, partial_ord: Option<PartialOrdFnTyped<T>>) -> Self {
826        self.partial_ord = partial_ord;
827        self
828    }
829
830    /// Sets the ord function for this builder.
831    pub const fn ord(mut self, ord: CmpFnTyped<T>) -> Self {
832        self.ord = Some(ord);
833        self
834    }
835
836    /// Sets the ord function for this builder if Some.
837    pub const fn ord_maybe(mut self, ord: Option<CmpFnTyped<T>>) -> Self {
838        self.ord = ord;
839        self
840    }
841
842    /// Sets the hash function for this builder.
843    pub const fn hash(mut self, hash: HashFnTyped<T>) -> Self {
844        self.hash = Some(hash);
845        self
846    }
847
848    /// Sets the hash function for this builder if Some.
849    pub const fn hash_maybe(mut self, hash: Option<HashFnTyped<T>>) -> Self {
850        self.hash = hash;
851        self
852    }
853
854    /// Overwrites the drop_in_place function for this builder.
855    ///
856    /// This is usually not necessary, the builder builder will default this to the appropriate type.
857    pub const fn drop_in_place(mut self, drop_in_place: DropInPlaceFn) -> Self {
858        self.drop_in_place = Some(drop_in_place);
859        self
860    }
861
862    /// Sets the invariants function for this builder.
863    pub const fn invariants(mut self, invariants: InvariantsFnTyped<T>) -> Self {
864        self.invariants = Some(invariants);
865        self
866    }
867
868    /// Sets the parse function for this builder.
869    pub const fn parse(mut self, parse: ParseFnTyped<T>) -> Self {
870        self.parse = Some(parse);
871        self
872    }
873
874    /// Sets the parse function for this builder if Some.
875    pub const fn parse_maybe(mut self, parse: Option<ParseFnTyped<T>>) -> Self {
876        self.parse = parse;
877        self
878    }
879
880    /// Sets the try_from function for this builder.
881    pub const fn try_from(mut self, try_from: TryFromFnTyped<T>) -> Self {
882        self.try_from = Some(try_from);
883        self
884    }
885
886    /// Sets the try_into_inner function for this builder.
887    pub const fn try_into_inner(mut self, try_into_inner: TryIntoInnerFnTyped<T>) -> Self {
888        self.try_into_inner = Some(try_into_inner);
889        self
890    }
891
892    /// Sets the borrow_inner function for this builder.
893    pub const fn try_borrow_inner(mut self, try_borrow_inner: TryBorrowInnerFnTyped<T>) -> Self {
894        self.try_borrow_inner = Some(try_borrow_inner);
895        self
896    }
897
898    /// Builds the [`ValueVTable`] from the current state of the builder.
899    pub const fn build(self) -> ValueVTable {
900        ValueVTable {
901            type_name: self.type_name.unwrap(),
902            marker_traits: self.marker_traits,
903            invariants: unsafe {
904                mem::transmute::<Option<InvariantsFnTyped<T>>, Option<InvariantsFn>>(
905                    self.invariants,
906                )
907            },
908            display: unsafe {
909                mem::transmute::<Option<DisplayFnTyped<T>>, Option<DisplayFn>>(self.display)
910            },
911            debug: unsafe {
912                mem::transmute::<Option<DebugFnTyped<T>>, Option<DebugFn>>(self.debug)
913            },
914            default_in_place: unsafe {
915                mem::transmute::<Option<DefaultInPlaceFnTyped<T>>, Option<DefaultInPlaceFn>>(
916                    self.default_in_place,
917                )
918            },
919            clone_into: unsafe {
920                mem::transmute::<Option<CloneIntoFnTyped<T>>, Option<CloneIntoFn>>(self.clone_into)
921            },
922            eq: unsafe {
923                mem::transmute::<Option<PartialEqFnTyped<T>>, Option<PartialEqFn>>(self.eq)
924            },
925            partial_ord: unsafe {
926                mem::transmute::<Option<PartialOrdFnTyped<T>>, Option<PartialOrdFn>>(
927                    self.partial_ord,
928                )
929            },
930            ord: unsafe { mem::transmute::<Option<CmpFnTyped<T>>, Option<CmpFn>>(self.ord) },
931            hash: unsafe { mem::transmute::<Option<HashFnTyped<T>>, Option<HashFn>>(self.hash) },
932            parse: unsafe {
933                mem::transmute::<Option<ParseFnTyped<T>>, Option<ParseFn>>(self.parse)
934            },
935            try_from: unsafe {
936                mem::transmute::<Option<TryFromFnTyped<T>>, Option<TryFromFn>>(self.try_from)
937            },
938            try_into_inner: unsafe {
939                mem::transmute::<Option<TryIntoInnerFnTyped<T>>, Option<TryIntoInnerFn>>(
940                    self.try_into_inner,
941                )
942            },
943            try_borrow_inner: unsafe {
944                mem::transmute::<Option<TryBorrowInnerFnTyped<T>>, Option<TryBorrowInnerFn>>(
945                    self.try_borrow_inner,
946                )
947            },
948            drop_in_place: if let Some(drop_in_place) = self.drop_in_place {
949                Some(drop_in_place)
950            } else if mem::needs_drop::<T>() {
951                Some(|value| unsafe { value.drop_in_place::<T>() })
952            } else {
953                None
954            },
955        }
956    }
957}