fromsoftware_shared/
empty.rs1use std::{fmt, iter::FusedIterator, mem::MaybeUninit, ptr::NonNull};
2
3#[repr(transparent)]
17pub struct MaybeEmpty<T>(MaybeUninit<T>)
20where
21 T: IsEmpty;
22
23pub unsafe trait IsEmpty: Sized {
31 fn is_empty(value: &MaybeEmpty<Self>) -> bool;
34}
35
36impl<T> MaybeEmpty<T>
37where
38 T: IsEmpty,
39{
40 pub fn is_empty(&self) -> bool {
43 IsEmpty::is_empty(self)
44 }
45
46 pub fn as_non_null(&self) -> NonNull<T> {
50 NonNull::from_ref(self).cast::<T>()
51 }
52
53 pub fn as_option(&self) -> Option<&T> {
55 if self.is_empty() {
56 None
57 } else {
58 Some(unsafe { self.as_non_null().as_ref() })
60 }
61 }
62
63 pub fn as_option_mut(&mut self) -> Option<&mut T> {
65 if self.is_empty() {
66 None
67 } else {
68 Some(unsafe { self.as_non_null().as_mut() })
70 }
71 }
72}
73
74impl<T> fmt::Debug for MaybeEmpty<T>
75where
76 T: IsEmpty + fmt::Debug,
77{
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 if let Some(value) = self.as_option() {
80 value.fmt(f)
81 } else {
82 write!(f, "<empty>")
83 }
84 }
85}
86
87pub struct NonEmptyIter<'a, E, I>(I)
89where
90 E: IsEmpty + 'a,
91 I: Iterator<Item = &'a MaybeEmpty<E>>;
92
93impl<'a, E, I> Iterator for NonEmptyIter<'a, E, I>
94where
95 E: IsEmpty + 'a,
96 I: Iterator<Item = &'a MaybeEmpty<E>>,
97{
98 type Item = &'a E;
99
100 fn next(&mut self) -> Option<Self::Item> {
101 loop {
102 match self.0.next() {
103 Some(entry) => {
104 if let Some(entry) = entry.as_option() {
105 return Some(entry);
106 }
107 }
108 None => return None,
109 }
110 }
111 }
112}
113
114impl<'a, E, I> FusedIterator for NonEmptyIter<'a, E, I>
115where
116 E: IsEmpty + 'a,
117 I: Iterator<Item = &'a MaybeEmpty<E>> + FusedIterator,
118{
119}
120
121pub trait NonEmptyIteratorExt<'a, E>: Iterator<Item = &'a MaybeEmpty<E>>
124where
125 E: IsEmpty + 'a,
126 Self: Sized,
127{
128 fn non_empty(self) -> NonEmptyIter<'a, E, Self>;
130}
131
132impl<'a, E, I> NonEmptyIteratorExt<'a, E> for I
133where
134 E: IsEmpty + 'a,
135 I: Iterator<Item = &'a MaybeEmpty<E>> + Sized,
136{
137 fn non_empty(self) -> NonEmptyIter<'a, E, Self> {
138 NonEmptyIter(self)
139 }
140}
141
142pub struct NonEmptyIterMut<'a, E, I>(I)
144where
145 E: IsEmpty + 'a,
146 I: Iterator<Item = &'a mut MaybeEmpty<E>>;
147
148impl<'a, E, I> Iterator for NonEmptyIterMut<'a, E, I>
149where
150 E: IsEmpty + 'a,
151 I: Iterator<Item = &'a mut MaybeEmpty<E>>,
152{
153 type Item = &'a mut E;
154
155 fn next(&mut self) -> Option<Self::Item> {
156 loop {
157 match self.0.next() {
158 Some(entry) => {
159 if let Some(entry) = entry.as_option_mut() {
160 return Some(entry);
161 }
162 }
163 None => return None,
164 }
165 }
166 }
167}
168
169pub trait NonEmptyIteratorMutExt<'a, E>: Iterator<Item = &'a mut MaybeEmpty<E>>
172where
173 E: IsEmpty + 'a,
174 Self: Sized,
175{
176 fn non_empty(self) -> NonEmptyIterMut<'a, E, Self>;
178}
179
180impl<'a, E, I> NonEmptyIteratorMutExt<'a, E> for I
181where
182 E: IsEmpty + 'a,
183 I: Iterator<Item = &'a mut MaybeEmpty<E>> + Sized,
184{
185 fn non_empty(self) -> NonEmptyIterMut<'a, E, Self> {
186 NonEmptyIterMut(self)
187 }
188}