structural_typing/
presence.rs1use core::marker::PhantomData;
4
5use crate::{
6 access::Access,
7 extract::{Extract, TryExtract},
8};
9
10pub struct Present;
12pub struct Optional;
14pub struct Absent;
16
17pub trait Presence {
19 type OptionOrSelf: Presence;
21 type Or<Other: Presence>: Presence;
23 type Output<T>: Access<T>
25 + Extract<PhantomData<T>, T>
26 + Extract<Option<T>, T>
27 + Extract<Self::Output<T>, T>
28 + TryExtract<Option<T>, T>
29 + InferPresence<T, Presence = Self>;
30
31 fn or<T, Other: Presence>(
33 self_: <Self as Presence>::Output<T>,
34 other: Other::Output<T>,
35 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T>;
36
37 fn option_or_self<T>(
39 option: Option<T>,
40 self_: <Self as Presence>::Output<T>,
41 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T>;
42}
43
44pub trait InferPresence<T> {
46 type Presence: Presence<Output<T> = Self>;
48}
49
50impl<T> InferPresence<T> for T {
51 type Presence = Present;
52}
53
54impl<T> InferPresence<T> for Option<T> {
55 type Presence = Optional;
56}
57
58impl<T> InferPresence<T> for PhantomData<T> {
59 type Presence = Absent;
60}
61
62impl Presence for Present {
63 type OptionOrSelf = Present;
64 type Or<Other: Presence> = Present;
65 type Output<T> = T;
66
67 #[inline]
68 fn or<T, Other: Presence>(
69 self_: <Self as Presence>::Output<T>,
70 _other: Other::Output<T>,
71 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
72 self_
73 }
74
75 #[inline]
76 fn option_or_self<T>(
77 option: Option<T>,
78 self_: <Self as Presence>::Output<T>,
79 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
80 option.unwrap_or(self_)
81 }
82}
83
84impl Presence for Optional {
85 type OptionOrSelf = Optional;
86 type Or<Other: Presence> = Other::OptionOrSelf;
87 type Output<T> = Option<T>;
88
89 #[inline]
90 fn or<T, Other: Presence>(
91 self_: <Self as Presence>::Output<T>,
92 other: Other::Output<T>,
93 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
94 Other::option_or_self(self_, other)
95 }
96
97 #[inline]
98 fn option_or_self<T>(
99 option: Option<T>,
100 self_: <Self as Presence>::Output<T>,
101 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
102 option.or(self_)
103 }
104}
105
106impl Presence for Absent {
107 type OptionOrSelf = Optional;
108 type Or<Other: Presence> = Other;
109 type Output<T> = PhantomData<T>;
110
111 #[inline]
112 fn or<T, Other: Presence>(
113 _self: <Self as Presence>::Output<T>,
114 other: Other::Output<T>,
115 ) -> <<Self as Presence>::Or<Other> as Presence>::Output<T> {
116 other
117 }
118
119 #[inline]
120 fn option_or_self<T>(
121 option: Option<T>,
122 _self_: <Self as Presence>::Output<T>,
123 ) -> <<Self as Presence>::OptionOrSelf as Presence>::Output<T> {
124 option
125 }
126}