1use ::allocator_api2::alloc::Allocator;
16use ::allocator_api2::boxed::Box;
17use ::std::cell::Cell;
18use ::std::ptr::NonNull;
19
20use crate::cons::Cons;
21use crate::oncecell_ext::OnceCellExt;
22use crate::OnceCell;
23
24mod sealed {
25 pub trait Sealed {}
26}
27
28#[doc(hidden)]
38#[derive(Clone)]
39pub struct NextSlot<T: ?Sized, A: Allocator> {
40 cell: OnceCell<Box<Cons<T, T, A>, A>>,
41}
42
43impl<T: ?Sized, A: Allocator> NextSlot<T, A> {
44 pub(crate) fn new() -> Self {
45 Self {
46 cell: OnceCell::new(),
47 }
48 }
49
50 pub(crate) fn get(&self) -> Option<&Box<Cons<T, T, A>, A>> {
51 self.cell.get()
52 }
53
54 pub(crate) fn get_mut(&mut self) -> Option<&mut Box<Cons<T, T, A>, A>> {
55 self.cell.get_mut()
56 }
57
58 pub(crate) fn set(&self, value: Box<Cons<T, T, A>, A>) -> Result<(), Box<Cons<T, T, A>, A>> {
59 self.cell.set(value)
60 }
61
62 pub(crate) fn take(&mut self) -> Option<Box<Cons<T, T, A>, A>> {
63 self.cell.take()
64 }
65
66 pub(crate) fn try_insert2(
67 &self,
68 value: Box<Cons<T, T, A>, A>,
69 ) -> Result<&Box<Cons<T, T, A>, A>, (&Box<Cons<T, T, A>, A>, Box<Cons<T, T, A>, A>)> {
70 self.cell.try_insert2(value)
71 }
72}
73
74#[doc(hidden)]
78pub trait CacheMode<T: ?Sized, A: Allocator>: sealed::Sealed + Clone {
79 fn cached_len(&self) -> Option<usize> {
81 None
82 }
83
84 fn tail_slot_opt<'a>(&'a self) -> Option<&'a NextSlot<T, A>> {
88 None
89 }
90
91 fn on_push_success(&self, _next_slot: &NextSlot<T, A>) {}
95
96 fn on_remove_success(&self) {}
98
99 fn on_clear(&self) {}
101
102 fn on_structure_change(&self);
106}
107
108#[derive(Clone, Copy, Default)]
110pub struct NoCache;
111
112impl sealed::Sealed for NoCache {}
113
114impl<T: ?Sized, A: Allocator> CacheMode<T, A> for NoCache {
115 fn on_structure_change(&self) {}
116}
117
118pub struct WithTail<T: ?Sized, A: Allocator> {
125 next_slot: Cell<Option<SlotPtr<T, A>>>,
126}
127
128type SlotPtr<T, A> = NonNull<NextSlot<T, A>>;
129
130impl<T: ?Sized, A: Allocator> Clone for WithTail<T, A> {
131 fn clone(&self) -> Self {
132 Self::new()
134 }
135}
136
137impl<T: ?Sized, A: Allocator> sealed::Sealed for WithTail<T, A> {}
138
139impl<T: ?Sized, A: Allocator> CacheMode<T, A> for WithTail<T, A> {
140 fn tail_slot_opt<'a>(&'a self) -> Option<&'a NextSlot<T, A>> {
141 if let Some(p) = self.next_slot.get() {
142 let slot = unsafe { p.as_ref() };
143 if slot.get().is_none() {
145 return Some(slot);
146 }
147 }
148 None
149 }
150
151 fn on_push_success(&self, next_slot: &NextSlot<T, A>) {
152 self.next_slot.set(Some(NonNull::from(next_slot)));
153 }
154
155 fn on_structure_change(&self) {
156 self.next_slot.set(None);
157 }
158}
159
160impl<T: ?Sized, A: Allocator> WithTail<T, A> {
161 pub(crate) fn new() -> Self {
162 Self {
163 next_slot: Cell::new(None),
164 }
165 }
166}
167
168impl<T: ?Sized, A: Allocator> Default for WithTail<T, A> {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174pub struct WithLen<T: ?Sized, A: Allocator> {
176 len: Cell<usize>,
177 _phantom: ::std::marker::PhantomData<fn(&T, &A)>,
178}
179
180impl<T: ?Sized, A: Allocator> Clone for WithLen<T, A> {
181 fn clone(&self) -> Self {
182 Self {
183 len: Cell::new(self.len.get()),
184 _phantom: ::std::marker::PhantomData,
185 }
186 }
187}
188
189impl<T: ?Sized, A: Allocator> sealed::Sealed for WithLen<T, A> {}
190
191impl<T: ?Sized, A: Allocator> CacheMode<T, A> for WithLen<T, A> {
192 fn cached_len(&self) -> Option<usize> {
193 Some(self.len.get())
194 }
195
196 fn on_push_success(&self, _next_slot: &NextSlot<T, A>) {
197 self.len.set(self.len.get() + 1);
198 }
199
200 fn on_remove_success(&self) {
201 self.len.set(self.len.get() - 1);
202 }
203
204 fn on_clear(&self) {
205 self.len.set(0);
206 }
207
208 fn on_structure_change(&self) {
209 }
211}
212
213impl<T: ?Sized, A: Allocator> WithLen<T, A> {
214 pub(crate) fn new() -> Self {
215 Self {
216 len: Cell::new(0),
217 _phantom: ::std::marker::PhantomData,
218 }
219 }
220}
221
222impl<T: ?Sized, A: Allocator> Default for WithLen<T, A> {
223 fn default() -> Self {
224 Self::new()
225 }
226}
227
228pub struct WithTailLen<T: ?Sized, A: Allocator> {
230 next_slot: Cell<Option<SlotPtr<T, A>>>,
231 len: Cell<usize>,
232}
233
234impl<T: ?Sized, A: Allocator> Clone for WithTailLen<T, A> {
235 fn clone(&self) -> Self {
236 Self {
239 next_slot: Cell::new(None),
240 len: Cell::new(self.len.get()),
241 }
242 }
243}
244
245impl<T: ?Sized, A: Allocator> sealed::Sealed for WithTailLen<T, A> {}
246
247impl<T: ?Sized, A: Allocator> CacheMode<T, A> for WithTailLen<T, A> {
248 fn cached_len(&self) -> Option<usize> {
249 Some(self.len.get())
250 }
251
252 fn tail_slot_opt<'a>(&'a self) -> Option<&'a NextSlot<T, A>> {
253 if let Some(p) = self.next_slot.get() {
254 let slot = unsafe { p.as_ref() };
255 if slot.get().is_none() {
256 return Some(slot);
257 }
258 }
259 None
260 }
261
262 fn on_push_success(&self, next_slot: &NextSlot<T, A>) {
263 self.len.set(self.len.get() + 1);
264 self.next_slot.set(Some(NonNull::from(next_slot)));
265 }
266
267 fn on_remove_success(&self) {
268 self.len.set(self.len.get() - 1);
269 }
270
271 fn on_clear(&self) {
272 self.len.set(0);
273 self.next_slot.set(None);
274 }
275
276 fn on_structure_change(&self) {
277 self.next_slot.set(None);
279 }
280}
281
282impl<T: ?Sized, A: Allocator> WithTailLen<T, A> {
283 pub(crate) fn new() -> Self {
284 Self {
285 next_slot: Cell::new(None),
286 len: Cell::new(0),
287 }
288 }
289}
290
291impl<T: ?Sized, A: Allocator> Default for WithTailLen<T, A> {
292 fn default() -> Self {
293 Self::new()
294 }
295}