structural_typing/
presence.rs

1//! Type-level markers for field presence states.
2
3use core::marker::PhantomData;
4
5use crate::access::Access;
6
7/// Marker indicating a field is present with a concrete value.
8pub struct Present;
9/// Marker indicating a field may or may not be present (Option).
10pub struct Optional;
11/// Marker indicating a field is absent (`PhantomData`).
12pub struct Absent;
13
14/// Trait for type-level presence markers with associated container types.
15pub trait Presence {
16    /// The presence state when combined with an Option.
17    type OptionOrSelf: Presence;
18    /// Result of merging this presence with another.
19    type Or<Other: Presence>: Presence;
20    /// What remains from `Source` when extracting `Self`. `Present/Optional` → `Absent`; `Absent` → `Source`.
21    type RemainderFrom<Source: Presence>: Presence;
22    /// The container type for values with this presence (T, Option\<T>, or `PhantomData`\<T>).
23    type Output<T>: Access<T>;
24
25    /// Merge two values, preferring the first if present.
26    fn or<T, Other: Presence>(
27        self_: <Self as Presence>::Output<T>,
28        other: Other::Output<T>,
29    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T>;
30
31    /// Convert an Option into the appropriate presence state.
32    fn option_or_self<T>(
33        option: Option<T>,
34        self_: <Self as Presence>::Output<T>,
35    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T>;
36}
37
38/// Infers presence state from value type: `T` → Present, `Option<T>` → Optional, `PhantomData<T>` → Absent.
39pub trait InferPresence<T> {
40    /// The presence state corresponding to this value type.
41    type Presence: Presence<Output<T> = Self>;
42}
43
44impl<T> InferPresence<T> for T {
45    type Presence = Present;
46}
47
48impl<T> InferPresence<T> for Option<T> {
49    type Presence = Optional;
50}
51
52impl<T> InferPresence<T> for PhantomData<T> {
53    type Presence = Absent;
54}
55
56impl Presence for Present {
57    type OptionOrSelf = Present;
58    type Or<Other: Presence> = Present;
59    type RemainderFrom<Source: Presence> = Absent;
60    type Output<T> = T;
61
62    #[inline]
63    fn or<T, Other: Presence>(
64        self_: <Self as Presence>::Output<T>,
65        _other: Other::Output<T>,
66    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
67        self_
68    }
69
70    #[inline]
71    fn option_or_self<T>(
72        option: Option<T>,
73        self_: <Self as Presence>::Output<T>,
74    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
75        option.unwrap_or(self_)
76    }
77}
78
79impl Presence for Optional {
80    type OptionOrSelf = Optional;
81    type Or<Other: Presence> = Other::OptionOrSelf;
82    type RemainderFrom<Source: Presence> = Absent;
83    type Output<T> = Option<T>;
84
85    #[inline]
86    fn or<T, Other: Presence>(
87        self_: <Self as Presence>::Output<T>,
88        other: Other::Output<T>,
89    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
90        Other::option_or_self(self_, other)
91    }
92
93    #[inline]
94    fn option_or_self<T>(
95        option: Option<T>,
96        self_: <Self as Presence>::Output<T>,
97    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
98        option.or(self_)
99    }
100}
101
102impl Presence for Absent {
103    type OptionOrSelf = Optional;
104    type Or<Other: Presence> = Other;
105    type RemainderFrom<Source: Presence> = Source;
106    type Output<T> = PhantomData<T>;
107
108    #[inline]
109    fn or<T, Other: Presence>(
110        _self: <Self as Presence>::Output<T>,
111        other: Other::Output<T>,
112    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
113        other
114    }
115
116    #[inline]
117    fn option_or_self<T>(
118        option: Option<T>,
119        _self_: <Self as Presence>::Output<T>,
120    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
121        option
122    }
123}