fromsoftware_shared/
empty.rs1use std::{fmt, iter::FusedIterator, mem::MaybeUninit, ops::Drop, ptr::NonNull};
2
3#[repr(transparent)]
17pub struct MaybeEmpty<T>(MaybeUninit<T>)
20where
21 T: IsEmpty;
22
23pub unsafe trait IsEmpty: Sized {
32 fn is_empty(value: &MaybeEmpty<Self>) -> bool;
35}
36
37impl<T> MaybeEmpty<T>
38where
39 T: IsEmpty,
40{
41 pub fn new(value: T) -> MaybeEmpty<T> {
43 MaybeEmpty(MaybeUninit::new(value))
44 }
45
46 pub fn is_empty(&self) -> bool {
49 IsEmpty::is_empty(self)
50 }
51
52 pub fn as_non_null(&self) -> NonNull<T> {
56 NonNull::from_ref(self).cast::<T>()
57 }
58
59 pub fn as_option(&self) -> Option<&T> {
61 if self.is_empty() {
62 None
63 } else {
64 Some(unsafe { self.as_non_null().as_ref() })
66 }
67 }
68
69 pub fn as_option_mut(&mut self) -> Option<&mut T> {
71 if self.is_empty() {
72 None
73 } else {
74 Some(unsafe { self.as_non_null().as_mut() })
76 }
77 }
78}
79
80impl<T> fmt::Debug for MaybeEmpty<T>
81where
82 T: IsEmpty + fmt::Debug,
83{
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 if let Some(value) = self.as_option() {
86 value.fmt(f)
87 } else {
88 write!(f, "<empty>")
89 }
90 }
91}
92
93impl<T> From<T> for MaybeEmpty<T>
94where
95 T: IsEmpty,
96{
97 fn from(value: T) -> MaybeEmpty<T> {
98 MaybeEmpty(MaybeUninit::new(value))
99 }
100}
101
102impl<T> Drop for MaybeEmpty<T>
103where
104 T: IsEmpty,
105{
106 fn drop(&mut self) {
107 if self.is_empty() {
108 unsafe { self.0.assume_init_drop() };
109 }
110 }
111}
112
113pub struct NonEmptyIter<'a, E, I>(I)
115where
116 E: IsEmpty + 'a,
117 I: Iterator<Item = &'a MaybeEmpty<E>>;
118
119impl<'a, E, I> Iterator for NonEmptyIter<'a, E, I>
120where
121 E: IsEmpty + 'a,
122 I: Iterator<Item = &'a MaybeEmpty<E>>,
123{
124 type Item = &'a E;
125
126 fn next(&mut self) -> Option<Self::Item> {
127 loop {
128 match self.0.next() {
129 Some(entry) => {
130 if let Some(entry) = entry.as_option() {
131 return Some(entry);
132 }
133 }
134 None => return None,
135 }
136 }
137 }
138}
139
140impl<'a, E, I> FusedIterator for NonEmptyIter<'a, E, I>
141where
142 E: IsEmpty + 'a,
143 I: Iterator<Item = &'a MaybeEmpty<E>> + FusedIterator,
144{
145}
146
147pub trait NonEmptyIteratorExt<'a, E>: Iterator<Item = &'a MaybeEmpty<E>>
150where
151 E: IsEmpty + 'a,
152 Self: Sized,
153{
154 fn non_empty(self) -> NonEmptyIter<'a, E, Self>;
156}
157
158impl<'a, E, I> NonEmptyIteratorExt<'a, E> for I
159where
160 E: IsEmpty + 'a,
161 I: Iterator<Item = &'a MaybeEmpty<E>> + Sized,
162{
163 fn non_empty(self) -> NonEmptyIter<'a, E, Self> {
164 NonEmptyIter(self)
165 }
166}
167
168pub struct NonEmptyIterMut<'a, E, I>(I)
170where
171 E: IsEmpty + 'a,
172 I: Iterator<Item = &'a mut MaybeEmpty<E>>;
173
174impl<'a, E, I> Iterator for NonEmptyIterMut<'a, E, I>
175where
176 E: IsEmpty + 'a,
177 I: Iterator<Item = &'a mut MaybeEmpty<E>>,
178{
179 type Item = &'a mut E;
180
181 fn next(&mut self) -> Option<Self::Item> {
182 loop {
183 match self.0.next() {
184 Some(entry) => {
185 if let Some(entry) = entry.as_option_mut() {
186 return Some(entry);
187 }
188 }
189 None => return None,
190 }
191 }
192 }
193}
194
195pub trait NonEmptyIteratorMutExt<'a, E>: Iterator<Item = &'a mut MaybeEmpty<E>>
198where
199 E: IsEmpty + 'a,
200 Self: Sized,
201{
202 fn non_empty(self) -> NonEmptyIterMut<'a, E, Self>;
204}
205
206impl<'a, E, I> NonEmptyIteratorMutExt<'a, E> for I
207where
208 E: IsEmpty + 'a,
209 I: Iterator<Item = &'a mut MaybeEmpty<E>> + Sized,
210{
211 fn non_empty(self) -> NonEmptyIterMut<'a, E, Self> {
212 NonEmptyIterMut(self)
213 }
214}