structural_typing/
presence.rs1use core::marker::PhantomData;
4
5use crate::{access::Access, extract::Extract};
6
7pub struct Present;
9pub struct Optional;
11pub struct Absent;
13
14pub trait Presence {
16 type OptionOrSelf: Presence;
18 type Or<Other: Presence>: Presence;
20 type Output<T>: Access<T>
22 + Extract<PhantomData<T>, T>
23 + Extract<Option<T>, T>
24 + Extract<Self::Output<T>, T>;
25
26 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 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
39pub trait InferPresence<T> {
41 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}