structural_typing/
presence.rs1use core::marker::PhantomData;
4
5use crate::{access::Access, extract::{Extract, TryExtract}};
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 + TryExtract<Option<T>, T>;
26
27 fn or<T, Other: Presence>(
29 self_: <Self as Presence>::Output<T>,
30 other: Other::Output<T>,
31 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T>;
32
33 fn option_or_self<T>(
35 option: Option<T>,
36 self_: <Self as Presence>::Output<T>,
37 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T>;
38}
39
40pub trait InferPresence<T> {
42 type Presence: Presence<Output<T> = Self>;
44}
45
46impl<T> InferPresence<T> for T {
47 type Presence = Present;
48}
49
50impl<T> InferPresence<T> for Option<T> {
51 type Presence = Optional;
52}
53
54impl<T> InferPresence<T> for PhantomData<T> {
55 type Presence = Absent;
56}
57
58impl Presence for Present {
59 type OptionOrSelf = Present;
60 type Or<Other: Presence> = Present;
61 type Output<T> = T;
62
63 #[inline]
64 fn or<T, Other: Presence>(
65 self_: <Self as Presence>::Output<T>,
66 _other: Other::Output<T>,
67 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
68 self_
69 }
70
71 #[inline]
72 fn option_or_self<T>(
73 option: Option<T>,
74 self_: <Self as Presence>::Output<T>,
75 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
76 option.unwrap_or(self_)
77 }
78}
79
80impl Presence for Optional {
81 type OptionOrSelf = Optional;
82 type Or<Other: Presence> = Other::OptionOrSelf;
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 Output<T> = PhantomData<T>;
106
107 #[inline]
108 fn or<T, Other: Presence>(
109 _self: <Self as Presence>::Output<T>,
110 other: Other::Output<T>,
111 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
112 other
113 }
114
115 #[inline]
116 fn option_or_self<T>(
117 option: Option<T>,
118 _self_: <Self as Presence>::Output<T>,
119 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
120 option
121 }
122}