structural_typing/
presence.rs

1//! Type-level markers for field presence states.
2
3use core::marker::PhantomData;
4
5use crate::{access::Access, extract::Extract};
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    /// Presence when combined with Option.
17    type OptionOrSelf: Presence;
18    /// Result of merging this presence with another.
19    type Or<Other: Presence>: Presence;
20    /// Container type (T, Option\<T>, or `PhantomData`\<T>).
21    type Output<T>: Access<T>
22        + Extract<PhantomData<T>, T>
23        + Extract<Option<T>, T>
24        + Extract<Self::Output<T>, T>;
25
26    /// Merge two values, preferring the first if present.
27    fn or<T, Other: Presence>(
28        self_: <Self as Presence>::Output<T>,
29        other: Other::Output<T>,
30    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T>;
31
32    /// Convert an Option into the appropriate presence state.
33    fn option_or_self<T>(
34        option: Option<T>,
35        self_: <Self as Presence>::Output<T>,
36    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T>;
37}
38
39/// Infers presence state from value type: `T` → Present, `Option<T>` → Optional, `PhantomData<T>` → Absent.
40pub trait InferPresence<T> {
41    /// The presence state corresponding to this value type.
42    type Presence: Presence<Output<T> = Self>;
43}
44
45impl<T> InferPresence<T> for T {
46    type Presence = Present;
47}
48
49impl<T> InferPresence<T> for Option<T> {
50    type Presence = Optional;
51}
52
53impl<T> InferPresence<T> for PhantomData<T> {
54    type Presence = Absent;
55}
56
57impl Presence for Present {
58    type OptionOrSelf = Present;
59    type Or<Other: Presence> = Present;
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 Output<T> = Option<T>;
83
84    #[inline]
85    fn or<T, Other: Presence>(
86        self_: <Self as Presence>::Output<T>,
87        other: Other::Output<T>,
88    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
89        Other::option_or_self(self_, other)
90    }
91
92    #[inline]
93    fn option_or_self<T>(
94        option: Option<T>,
95        self_: <Self as Presence>::Output<T>,
96    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
97        option.or(self_)
98    }
99}
100
101impl Presence for Absent {
102    type OptionOrSelf = Optional;
103    type Or<Other: Presence> = Other;
104    type Output<T> = PhantomData<T>;
105
106    #[inline]
107    fn or<T, Other: Presence>(
108        _self: <Self as Presence>::Output<T>,
109        other: Other::Output<T>,
110    ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
111        other
112    }
113
114    #[inline]
115    fn option_or_self<T>(
116        option: Option<T>,
117        _self_: <Self as Presence>::Output<T>,
118    ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
119        option
120    }
121}