once_list2/
lib.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![doc = include_str!("../README.md")]
16#![cfg_attr(feature = "nightly", feature(allocator_api))]
17#![cfg_attr(feature = "nightly", feature(box_into_inner))]
18#![cfg_attr(feature = "nightly", feature(coerce_unsized))]
19#![cfg_attr(feature = "nightly", feature(doc_cfg))]
20#![cfg_attr(feature = "nightly", feature(once_cell_try_insert))]
21#![cfg_attr(feature = "nightly", feature(ptr_metadata))]
22#![cfg_attr(feature = "nightly", feature(unsize))]
23
24use ::allocator_api2::alloc;
25use ::allocator_api2::alloc::{Allocator, Global};
26use ::allocator_api2::boxed::Box;
27use ::std::any::Any;
28use ::std::fmt::Debug;
29use ::std::hash::Hash;
30#[cfg(feature = "nightly")]
31use ::std::marker::Unsize;
32use ::std::ops::DerefMut;
33
34#[cfg(not(feature = "sync"))]
35use ::std::cell::OnceCell;
36use ::std::ptr::NonNull;
37#[cfg(feature = "sync")]
38use ::std::sync::OnceLock as OnceCell;
39
40/// A single linked list which behaves like [`std::cell::OnceCell`], but for multiple values.
41///
42/// # Usage
43///
44/// A simple example:
45///
46/// ```rust
47/// use once_list2::OnceList;
48///
49/// // Create a new empty list. Note that the variable is immutable.
50/// let list = OnceList::<i32>::new();
51///
52/// // You can push values to the list without the need for mutability.
53/// list.push(1);
54/// list.push(2);
55///
56/// // Or you can push multiple values at once.
57/// list.extend([3, 4, 5]);
58///
59/// // You can iterate over the list.
60/// assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5]);
61///
62/// // Some methods are mutable only.
63/// let mut list_mut = list;
64///
65/// // You can remove (take) a value from the list.
66/// let removed = list_mut.remove(|&x| x % 2 == 0);
67/// assert_eq!(removed, Some(2));
68/// assert_eq!(list_mut.iter().copied().collect::<Vec<_>>(), vec![1, 3, 4, 5]);
69/// ```
70///
71/// # Unsized types support
72///
73/// You can use the [unsized types] like `str`, `[u8]` or `dyn Display` as the value type of the `OnceList`.
74///
75/// If you are using the stable rust compiler, you can only use the `dyn Any` type as the unsized type.
76/// (Strictly speaking, you can use ANY type as the unsized type, but you can't do any actual operations
77/// like pushing, removing, etc.)
78///
79/// In the nightly compiler and with the `nightly` feature enabled, the additional methods like `push_unsized`
80/// and `remove_unsized_as` become available:
81///
82/// ```rust
83/// # #[cfg(not(feature = "nightly"))]
84/// # fn main() {}
85/// # #[cfg(feature = "nightly")]
86/// # fn main() {
87/// // This code only works with the nightly compiler and the `nightly` feature enabled.
88///
89/// use once_list2::OnceList;
90///
91/// // Creating a `OnceList` for `[i32]`, the unsized type.
92/// let list = OnceList::<[i32]>::new();
93///
94/// list.push_unsized([1] /* A sized array type, `[i32; 1]`, can be coerced into [i32].*/);
95/// list.push_unsized([2, 3] /* Same for `[i32; 2] type. */);
96///
97/// // The normal methods like `iter` are available because it returns a reference to the value.
98/// assert_eq!(list.iter().nth(0).unwrap(), &[1]);
99/// assert_eq!(list.iter().nth(1).unwrap(), &[2, 3]);
100///
101/// let mut list_mut = list;
102///
103/// // `remove_unsized_as` method allows you to check the unsized value type and remove it.
104/// let removed: Option<[i32; 2]> = unsafe {
105///     list_mut.remove_unsized_as(|x| if x.len() == 2 {
106///         Some(x.try_into().unwrap())
107///     } else {
108///         None
109///     })
110/// };
111/// // The removed value is an array, not a slice!
112/// assert_eq!(removed, Some([2, 3]));
113/// # }
114/// ```
115/// [unsized types]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
116///
117#[derive(Clone)]
118pub struct OnceList<T: ?Sized, A: Allocator = Global> {
119    head: OnceCell<Box<Cons<T, T, A>, A>>,
120    alloc: A,
121}
122
123/// A single linked list node.
124///
125/// Type parameter `T` and `U` are essentially the same type, but for rust's unsized coercion
126/// feature, we need to separate them.
127/// Then we can safely cast `&Cons<SizedT, U, A>` into `&Cons<UnsizedT, U, A>`.
128#[derive(Clone)]
129struct Cons<T: ?Sized, U: ?Sized, A: Allocator> {
130    next: OnceCell<Box<Cons<U, U, A>, A>>,
131    val: T,
132}
133
134impl<T: ?Sized> OnceList<T, Global> {
135    /// Creates a new empty `OnceList`. This method does not allocate.
136    pub fn new() -> Self {
137        Self {
138            head: OnceCell::new(),
139            alloc: Global,
140        }
141    }
142}
143impl<T: ?Sized, A: Allocator> OnceList<T, A> {
144    /// Creates a new empty `OnceList` with the given allocator. This method does not allocate.
145    pub fn new_in(alloc: A) -> Self {
146        Self {
147            head: OnceCell::new(),
148            alloc,
149        }
150    }
151
152    /// Returns the number of values in the list. This method is O(n).
153    pub fn len(&self) -> usize {
154        self.iter().count()
155    }
156
157    /// Returns `true` if the list is empty.
158    pub fn is_empty(&self) -> bool {
159        self.head.get().is_none()
160    }
161
162    /// Returns `true` if the list contains the value.
163    pub fn contains(&self, val: &T) -> bool
164    where
165        T: PartialEq,
166    {
167        self.iter().any(|v| v == val)
168    }
169
170    /// Returns a first value, if it exists.
171    pub fn first(&self) -> Option<&T> {
172        self.head.get().map(|c| &c.val)
173    }
174
175    /// Returns a mutable reference to the first value, if it exists.
176    pub fn first_mut(&mut self) -> Option<&mut T> {
177        self.head.get_mut().map(|c| &mut c.val)
178    }
179
180    /// Returns a last value, if it exists.
181    /// This method is O(n).
182    pub fn last(&self) -> Option<&T> {
183        let mut last_opt = None;
184        let mut next_cell = &self.head;
185        while let Some(next_box) = next_cell.get() {
186            last_opt = Some(&next_box.val);
187            next_cell = &next_box.next;
188        }
189        last_opt
190    }
191
192    /// Returns a mutable reference to the last value, if it exists.
193    /// This method is O(n).
194    pub fn last_mut(&mut self) -> Option<&mut T> {
195        let mut last_opt = None;
196        let mut next_cell = &mut self.head;
197        while let Some(next_box) = next_cell.get_mut() {
198            let next_cons = Box::deref_mut(next_box);
199            last_opt = Some(&mut next_cons.val);
200            next_cell = &mut next_cons.next;
201        }
202        last_opt
203    }
204
205    fn last_cell(&self) -> &OnceCell<Box<Cons<T, T, A>, A>> {
206        let mut next_cell = &self.head;
207        while let Some(next_box) = next_cell.get() {
208            next_cell = &next_box.next;
209        }
210        next_cell
211    }
212
213    /// Returns an iterator over the `&T` references in the list.
214    pub fn iter(&self) -> impl Iterator<Item = &T> {
215        let mut next_cell = &self.head;
216        ::std::iter::from_fn(move || match next_cell.get() {
217            Some(c) => {
218                next_cell = &c.next;
219                Some(&c.val)
220            }
221            None => None,
222        })
223    }
224
225    /// Returns an iterator over the `&mut T` references in the list.
226    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
227        struct Iter<'a, T: ?Sized, A: Allocator> {
228            next_cell: &'a mut OnceCell<Box<Cons<T, T, A>, A>>,
229        }
230        impl<'a, T: ?Sized, A: Allocator> Iterator for Iter<'a, T, A> {
231            type Item = &'a mut T;
232            fn next(&mut self) -> Option<Self::Item> {
233                let next_box = self.next_cell.get_mut()?;
234                // Need to cast the `self` lifetime to `&'a` to update the `Self::Item`.
235                let next_cons = unsafe { &mut *::std::ptr::from_mut(next_box.as_mut()) };
236                self.next_cell = &mut next_cons.next;
237                Some(&mut next_cons.val)
238            }
239        }
240        Iter {
241            next_cell: &mut self.head,
242        }
243    }
244
245    /// Clears the list, dropping all values.
246    pub fn clear(&mut self) {
247        self.head = OnceCell::new();
248    }
249
250    /// Returns an allocator of this struct.
251    pub fn allocator(&self) -> &A {
252        &self.alloc
253    }
254}
255
256impl<T: ?Sized, A: Allocator> OnceList<T, A> {
257    /// Removes the first value in the list that matches the predicate, and returns the value as a boxed value.
258    ///
259    /// This method supports the unsized value type `T` as well.
260    ///
261    /// Note that even though this method returns a boxed value, the box is something re-allcoated.
262    /// So this method might not be efficient as you expect.
263    #[cfg(feature = "nightly")]
264    #[cfg_attr(feature = "nightly", doc(cfg(feature = "nightly")))]
265    pub fn remove_into_box<P>(&mut self, pred: P) -> Option<Box<T, A>>
266    where
267        P: FnMut(&T) -> bool,
268    {
269        self.remove_inner(pred, |boxed_cons| boxed_cons.box_into_inner_box())
270    }
271
272    /// Removes the first value in the list that matches the predicate, and returns the value.
273    ///
274    /// The predicate function `pred` should return `Some(&U)` if the value is found,
275    /// and the returned reference `&U` must be the same address as the value given in the `pred`.
276    ///
277    /// # Safety
278    /// This method is unsafe because it requires the predicate to return a reference to the same address as the value.
279    #[cfg(feature = "nightly")]
280    #[cfg_attr(feature = "nightly", doc(cfg(feature = "nightly")))]
281    pub unsafe fn remove_unsized_as<P, U>(&mut self, mut pred: P) -> Option<U>
282    where
283        P: FnMut(&T) -> Option<&U>,
284    {
285        let found_sized_ptr: OnceCell<*const U> = OnceCell::new();
286        self.remove_inner(
287            |val| {
288                if let Some(val) = pred(val) {
289                    // We only set the value once, so this is safe.
290                    found_sized_ptr.set(val as *const U).unwrap();
291                    true
292                } else {
293                    false
294                }
295            },
296            |boxed_cons| -> U {
297                // Given the boxed cons with the unsized value type `T`,
298                // and returns the sized type value `U` by value (i.e. out of the box).
299
300                // We are sure the `found_sized_ptr` is set.
301                let found_sized_ptr: *const U = *found_sized_ptr.get().unwrap();
302
303                let cons_layout = alloc::Layout::for_value::<Cons<T, T, A>>(&boxed_cons);
304                let (cons_ptr, alloc) = Box::into_non_null_with_allocator(boxed_cons);
305                let val_ptr = &unsafe { cons_ptr.as_ref() }.val as *const T;
306
307                // Double check the ptr returned by the `pred` is the same as the pointer we extracted from the cons.
308                debug_assert_eq!(val_ptr as *const U, found_sized_ptr);
309
310                // Load (memcpy) the value into the output variable.
311                let result = unsafe { ::std::ptr::read(val_ptr as *const U) };
312
313                // Free the cons memory.
314                unsafe { alloc.deallocate(cons_ptr.cast(), cons_layout) };
315
316                result
317            },
318        )
319    }
320
321    /// An inner implementeation for `remove_xxx` methods.
322    fn remove_inner<P, F, U>(&mut self, mut pred: P, mut f: F) -> Option<U>
323    where
324        P: FnMut(&T) -> bool,
325        F: FnMut(Box<Cons<T, T, A>, A>) -> U,
326    {
327        let mut next_cell = &mut self.head;
328        while let Some(next_ref) = next_cell.get() {
329            if pred(&next_ref.val) {
330                // Safe because we are sure the `next_cell` value is set.
331                let mut next_box = next_cell.take().unwrap();
332
333                // reconnect the list
334                if let Some(next_next) = next_box.next.take() {
335                    let _ = next_cell.set(next_next);
336                }
337
338                return Some(f(next_box));
339            }
340            // Safe because we are sure the `next_cell` value is set.
341            next_cell = &mut next_cell.get_mut().unwrap().next;
342        }
343        None
344    }
345}
346
347impl<T: ?Sized, A: Allocator + Clone> OnceList<T, A> {
348    /// An unsized version of the [`OnceList::push`] method.
349    ///
350    /// You can push a sized value to the list. For exaple, you can push `[i32; 3]` to the list of `[i32]`.
351    #[cfg(feature = "nightly")]
352    #[cfg_attr(feature = "nightly", doc(cfg(feature = "nightly")))]
353    pub fn push_unsized<U: Unsize<T>>(&self, val: U) -> &U {
354        let boxed_cons = Cons::new_boxed(val, self.alloc.clone());
355        self.push_inner(boxed_cons, |c| unsafe { &*(c as *const T as *const U) })
356    }
357
358    /// An inner implementation for the `push_xxx` methods.
359    fn push_inner<F, U>(&self, mut new_cons: Box<Cons<T, T, A>, A>, f: F) -> &U
360    where
361        F: FnOnce(&T) -> &U,
362    {
363        let mut next_cell = &self.head;
364        loop {
365            match next_cell.try_insert2(new_cons) {
366                Ok(new_cons) => {
367                    return f(&new_cons.val);
368                }
369                Err((cur_cons, new_cons2)) => {
370                    next_cell = &cur_cons.next;
371                    new_cons = new_cons2;
372                }
373            }
374        }
375    }
376}
377
378impl<T, A: Allocator> OnceList<T, A> {
379    /// Find a first value in the list matches the predicate, remove that item from the list,
380    /// and then returns that value.
381    pub fn remove<P>(&mut self, mut pred: P) -> Option<T>
382    where
383        P: FnMut(&T) -> bool,
384    {
385        self.remove_inner(&mut pred, |boxed_cons| Box::into_inner(boxed_cons).val)
386    }
387}
388
389impl<T, A: Allocator + Clone> OnceList<T, A> {
390    /// Appends a value to the list, and returns the reference to that value.
391    ///
392    /// Note that this method takes `&self`, not `&mut self`.
393    pub fn push(&self, val: T) -> &T {
394        let boxed_cons = Box::new_in(Cons::new(val), self.alloc.clone());
395        self.push_inner(boxed_cons, |c| c)
396    }
397
398    /// An almost same method with the [`std::iter::Extend::extend`],
399    /// though this method takes `&self` instead of `&mut self`.
400    ///
401    /// [`std::iter::Extend::extend`]: https://doc.rust-lang.org/std/iter/trait.Extend.html#tymethod.extend
402    pub fn extend<U: IntoIterator<Item = T>>(&self, iter: U) {
403        let mut last_cell = self.last_cell();
404        let alloc = self.allocator();
405        for val in iter {
406            let _ = last_cell.set(Box::new_in(Cons::new(val), A::clone(alloc)));
407            last_cell = &unsafe { &last_cell.get().unwrap_unchecked() }.next;
408        }
409    }
410}
411
412impl<A: Allocator + Clone> OnceList<dyn Any, A> {
413    /// Pushes an aribitrary value to the list, and returns the reference to that value.
414    ///
415    /// ```rust
416    /// use once_list2::OnceList;
417    /// use std::any::Any;
418    ///
419    /// let list = OnceList::<dyn Any>::new();
420    /// list.push_any(1);
421    /// list.push_any("hello");
422    ///
423    /// assert_eq!(list.iter().nth(0).unwrap().downcast_ref::<i32>(), Some(&1));
424    /// assert_eq!(list.iter().nth(1).unwrap().downcast_ref::<&str>(), Some(&"hello"));
425    /// ```
426    pub fn push_any<T: Any>(&self, val: T) -> &T {
427        let sized_box = Box::new_in(Cons::<T, dyn Any, A>::new(val), A::clone(&self.alloc));
428        // Because we are using the non-standard `Box`, we need to manually do the unsized coercions...
429        // Watching the PR:
430        // https://github.com/zakarumych/allocator-api2/pull/23
431        let unsized_box = unsafe {
432            let (sized_ptr, alloc) = Box::into_raw_with_allocator(sized_box);
433            // Pointer unsized corecion!
434            let unsized_ptr: *mut Cons<dyn Any, dyn Any, A> = sized_ptr;
435            Box::from_raw_in(unsized_ptr, alloc)
436        };
437        self.push_inner(
438            unsized_box,
439            // Safe because we know the given value is type `T`.
440            |c| c.downcast_ref::<T>().unwrap(),
441        )
442    }
443}
444
445impl<A: Allocator> OnceList<dyn Any, A> {
446    /// Finds the first value in the list that is the same type as `T`, and returns the reference to that value.
447    ///
448    /// ```rust
449    /// use once_list2::OnceList;
450    /// use std::any::Any;
451    ///
452    /// let list = OnceList::<dyn Any>::new();
453    /// list.push_any(1);
454    /// list.push_any("hello");
455    ///
456    /// assert_eq!(list.find_by_type::<i32>(), Some(&1));
457    /// assert_eq!(list.find_by_type::<&str>(), Some(&"hello"));
458    /// assert_eq!(list.find_by_type::<Vec<u8>>(), None);
459    /// ```
460    pub fn find_by_type<T: Any>(&self) -> Option<&T> {
461        self.iter().find_map(|val| val.downcast_ref())
462    }
463
464    /// Removes the first value in the list that is the same type as `T`, and returns the value.
465    ///
466    /// ```rust
467    /// use once_list2::OnceList;
468    /// use std::any::Any;
469    ///
470    /// let mut list = OnceList::<dyn Any>::new();
471    /// list.push_any(1);
472    /// list.push_any("hello");
473    ///
474    /// assert_eq!(list.remove_by_type::<i32>(), Some(1));
475    ///
476    /// assert_eq!(list.len(), 1);
477    /// assert_eq!(list.iter().nth(0).unwrap().downcast_ref::<&str>(), Some(&"hello"));
478    /// ```
479    pub fn remove_by_type<T: Any>(&mut self) -> Option<T> {
480        self.remove_inner(
481            |v| v.is::<T>(),
482            |boxed_cons| {
483                let cons_layout = alloc::Layout::for_value::<Cons<_, _, _>>(&boxed_cons);
484                let (cons_ptr, alloc) = Box::into_raw_with_allocator(boxed_cons);
485
486                let Cons {
487                    next: next_ref,
488                    val: val_any_ref,
489                } = unsafe { &*cons_ptr };
490                // drop the `next` field.
491                unsafe { ::std::ptr::read(next_ref) };
492
493                let val_ref = <dyn Any>::downcast_ref::<T>(val_any_ref).unwrap();
494                let val = unsafe { ::std::ptr::read(val_ref) };
495
496                unsafe {
497                    alloc.deallocate(NonNull::new_unchecked(cons_ptr as *mut u8), cons_layout);
498                }
499
500                val
501            },
502        )
503    }
504}
505
506impl<T: ?Sized> Default for OnceList<T, Global> {
507    fn default() -> Self {
508        Self::new()
509    }
510}
511
512impl<T: ?Sized + Debug, A: Allocator> Debug for OnceList<T, A> {
513    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
514        f.debug_list().entries(self.iter()).finish()
515    }
516}
517
518impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for OnceList<T, A> {
519    fn eq(&self, other: &Self) -> bool {
520        self.iter().eq(other.iter())
521    }
522}
523
524impl<T: ?Sized + Eq, A: Allocator> Eq for OnceList<T, A> {}
525
526impl<T: ?Sized + Hash, A: Allocator> Hash for OnceList<T, A> {
527    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
528        state.write_usize(self.len());
529        for val in self.iter() {
530            val.hash(state);
531        }
532    }
533}
534
535impl<T> FromIterator<T> for OnceList<T, Global> {
536    fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
537        let list = Self::new();
538        let mut last_cell = &list.head;
539        for val in iter {
540            let _ = last_cell.set(Box::new(Cons::new(val)));
541            last_cell = &unsafe { &last_cell.get().unwrap_unchecked() }.next;
542        }
543        list
544    }
545}
546
547impl<T, A: Allocator> IntoIterator for OnceList<T, A> {
548    type Item = T;
549    type IntoIter = IntoIter<T, A>;
550    fn into_iter(self) -> Self::IntoIter {
551        IntoIter(self.head)
552    }
553}
554
555pub struct IntoIter<T, A: Allocator>(OnceCell<Box<Cons<T, T, A>, A>>);
556
557impl<T, A: Allocator> Iterator for IntoIter<T, A> {
558    type Item = T;
559    fn next(&mut self) -> Option<Self::Item> {
560        let next_cell = self.0.take()?;
561        let next_cons = Box::into_inner(next_cell);
562        self.0 = next_cons.next;
563        Some(next_cons.val)
564    }
565}
566
567impl<T, A: Allocator + Clone> Extend<T> for OnceList<T, A> {
568    /// Due to the definition of the `Extend` trait, this method takes `&mut self`.
569    /// Use the [`OnceList::extend`] method instead if you want to use `&self`.
570    fn extend<U: IntoIterator<Item = T>>(&mut self, iter: U) {
571        <OnceList<T, A>>::extend(self, iter);
572    }
573}
574
575impl<T, U: ?Sized, A: Allocator> Cons<T, U, A> {
576    fn new(val: T) -> Self {
577        Self {
578            next: OnceCell::new(),
579            val,
580        }
581    }
582}
583
584#[cfg(feature = "nightly")]
585impl<T: ?Sized, A: Allocator> Cons<T, T, A> {
586    fn new_boxed<U>(val: U, alloc: A) -> Box<Self, A>
587    where
588        U: Unsize<T>,
589    {
590        // As mentioned in the [`Cons`]'s document, this unsized coercion cast is safe!
591        Box::<Cons<U, T, A>, A>::new_in(
592            Cons::<U, T, A> {
593                next: OnceCell::new(),
594                val: val,
595            },
596            alloc,
597        )
598    }
599
600    fn box_into_inner_box(self: Box<Self, A>) -> Box<T, A> {
601        use ::std::ptr::{metadata, NonNull};
602
603        let cons_layout = alloc::Layout::for_value::<Cons<T, T, A>>(&self);
604        let layout = alloc::Layout::for_value::<T>(&self.val);
605        let metadata = metadata(&self.val);
606        let (raw_cons, alloc) = Box::into_raw_with_allocator(self);
607        let dst = alloc.allocate(layout).unwrap();
608
609        // Make sure to drop the `cons`'s unused fields.
610        let Cons { next, val } = unsafe { &*raw_cons };
611        let _ = unsafe { ::std::ptr::read(next) };
612        let raw_src = val as *const T;
613
614        // Do memcpy.
615        unsafe {
616            ::std::ptr::copy_nonoverlapping(
617                raw_src.cast::<u8>(),
618                dst.cast::<u8>().as_ptr(),
619                layout.size(),
620            );
621        }
622
623        // free the `cons`'s memory. Not `drop` because we already dropped the fields.
624        unsafe {
625            alloc.deallocate(NonNull::new(raw_cons).unwrap().cast(), cons_layout);
626        }
627
628        // Create a new fat pointer for dst by combining the thin pointer and the metadata.
629        let dst = NonNull::<T>::from_raw_parts(dst.cast::<u8>(), metadata);
630
631        unsafe { Box::from_non_null_in(dst, alloc) }
632    }
633}
634
635/// A workaround for the missing `OnceCell::try_insert` method.
636trait OnceCellExt<T> {
637    fn try_insert2(&self, value: T) -> Result<&T, (&T, T)>;
638}
639#[cfg(not(feature = "nightly"))]
640impl<T> OnceCellExt<T> for OnceCell<T> {
641    fn try_insert2(&self, value: T) -> Result<&T, (&T, T)> {
642        // The both unsafe blocks are safe because it's sure the cell value is set.
643        match self.set(value) {
644            Ok(()) => Ok(unsafe { self.get().unwrap_unchecked() }),
645            Err(value) => Err((unsafe { self.get().unwrap_unchecked() }, value)),
646        }
647    }
648}
649#[cfg(feature = "nightly")]
650impl<T> OnceCellExt<T> for OnceCell<T> {
651    fn try_insert2(&self, value: T) -> Result<&T, (&T, T)> {
652        self.try_insert(value)
653    }
654}
655
656#[cfg(test)]
657mod tests {
658    use super::*;
659
660    #[test]
661    fn test_new() {
662        let list = OnceList::<i32>::new();
663        assert!(list.is_empty());
664        assert_eq!(list.len(), 0);
665        assert_eq!(list.iter().next(), None);
666    }
667
668    #[test]
669    fn test_default() {
670        let list = OnceList::<i32>::default();
671        assert!(list.is_empty());
672        assert_eq!(list.len(), 0);
673        assert_eq!(list.iter().next(), None);
674    }
675
676    #[test]
677    fn test_push() {
678        let list = OnceList::new();
679        let val = list.push(42);
680        assert_eq!(val, &42);
681        assert_eq!(list.len(), 1);
682        assert_eq!(list.clone().into_iter().collect::<Vec<_>>(), vec![42]);
683
684        list.push(100);
685        list.push(3);
686        assert_eq!(list.len(), 3);
687        assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![42, 100, 3]);
688    }
689
690    #[test]
691    fn test_from_iter() {
692        let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
693        assert_eq!(list.len(), 3);
694        assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3]);
695    }
696
697    #[test]
698    fn test_extend() {
699        let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
700        list.extend([4, 5, 6]);
701        assert_eq!(list.len(), 6);
702        assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6]);
703    }
704
705    #[test]
706    fn test_clear() {
707        let mut list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
708        list.clear();
709        assert!(list.is_empty());
710        assert_eq!(list.len(), 0);
711        assert_eq!(list.iter().next(), None);
712    }
713
714    #[test]
715    fn test_first_last() {
716        let empty_list = OnceList::<i32>::new();
717        assert_eq!(empty_list.first(), None);
718        assert_eq!(empty_list.last(), None);
719
720        let single_list = [42].into_iter().collect::<OnceList<_>>();
721        assert_eq!(single_list.first(), Some(&42));
722        assert_eq!(single_list.last(), Some(&42));
723
724        let multiple_list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
725        assert_eq!(multiple_list.first(), Some(&1));
726        assert_eq!(multiple_list.last(), Some(&3));
727    }
728
729    #[test]
730    fn test_contains() {
731        let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
732        assert!(list.contains(&1));
733        assert!(list.contains(&2));
734        assert!(list.contains(&3));
735        assert!(!list.contains(&0));
736        assert!(!list.contains(&4));
737
738        let empty_list = OnceList::<i32>::new();
739        assert!(!empty_list.contains(&1));
740    }
741
742    #[test]
743    fn test_remove() {
744        let mut list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
745        assert_eq!(list.remove(|&v| v == 2), Some(2));
746        assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &3]);
747
748        assert_eq!(list.remove(|&v| v == 0), None);
749        assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &3]);
750
751        assert_eq!(list.remove(|&v| v == 1), Some(1));
752        assert_eq!(list.iter().collect::<Vec<_>>(), vec![&3]);
753
754        assert_eq!(list.remove(|&v| v == 3), Some(3));
755        assert!(list.is_empty());
756    }
757
758    #[test]
759    fn test_eq() {
760        let list1 = [1, 2, 3].into_iter().collect::<OnceList<_>>();
761        let list2 = [1, 2, 3].into_iter().collect::<OnceList<_>>();
762        assert_eq!(list1, list2);
763
764        let list3 = [1, 2, 4].into_iter().collect::<OnceList<_>>();
765        assert_ne!(list1, list3);
766
767        let list4 = OnceList::<i32>::new();
768        assert_eq!(list4, list4);
769        assert_ne!(list1, list4);
770    }
771
772    #[test]
773    fn test_hash() {
774        use ::std::hash::{DefaultHasher, Hasher};
775        let mut hasher1 = DefaultHasher::new();
776        let mut hasher2 = DefaultHasher::new();
777
778        let list1 = [1, 2, 3].into_iter().collect::<OnceList<_>>();
779        let list2 = [1, 2, 3].into_iter().collect::<OnceList<_>>();
780        list1.hash(&mut hasher1);
781        list2.hash(&mut hasher2);
782        assert_eq!(hasher1.finish(), hasher2.finish());
783
784        let list3 = [1, 2, 4].into_iter().collect::<OnceList<_>>();
785        let mut hasher3 = DefaultHasher::new();
786        list3.hash(&mut hasher3);
787        assert_ne!(hasher1.finish(), hasher3.finish());
788
789        // make sure the hasher is prefix-free.
790        // See https://doc.rust-lang.org/beta/std/hash/trait.Hash.html#prefix-collisions
791        let tuple1 = (
792            [1, 2].into_iter().collect::<OnceList<_>>(),
793            [3].into_iter().collect::<OnceList<_>>(),
794        );
795        let tuple2 = (
796            [1].into_iter().collect::<OnceList<_>>(),
797            [2, 3].into_iter().collect::<OnceList<_>>(),
798        );
799        let mut hasher4 = DefaultHasher::new();
800        let mut hasher5 = DefaultHasher::new();
801        tuple1.hash(&mut hasher4);
802        tuple2.hash(&mut hasher5);
803        assert_ne!(hasher4.finish(), hasher5.finish());
804    }
805
806    #[test]
807    #[cfg(feature = "nightly")]
808    fn test_unsized_slice_push() {
809        let list: OnceList<[i32]> = OnceList::new();
810        let first = list.push_unsized([1]);
811        let second = list.push_unsized([2, 3]);
812        assert_eq!(first, &[1]);
813        assert_eq!(second, &[2, 3]);
814
815        assert_eq!(list.iter().nth(0), Some(&[1] as &[i32]));
816        assert_eq!(list.iter().nth(1), Some(&[2, 3] as &[i32]));
817    }
818
819    #[test]
820    #[cfg(feature = "nightly")]
821    fn test_unsized_dyn_push() {
822        let list: OnceList<dyn ToString> = OnceList::new();
823        let first = list.push_unsized(1);
824        let second = list.push_unsized("hello");
825        assert_eq!(first.to_string(), "1");
826        assert_eq!(second.to_string(), "hello");
827
828        assert_eq!(
829            list.iter().nth(0).map(<dyn ToString>::to_string),
830            Some("1".to_string())
831        );
832        assert_eq!(
833            list.iter().nth(1).map(<dyn ToString>::to_string),
834            Some("hello".to_string())
835        );
836    }
837
838    #[test]
839    #[cfg(feature = "nightly")]
840    fn test_unsized_slice_remove_into_box() {
841        let list = OnceList::<[i32]>::new();
842        list.push_unsized([1]);
843        list.push_unsized([2, 3]);
844        list.push_unsized([4, 5, 6]);
845
846        let mut list = list;
847        let removed = list.remove_into_box(|s| s.len() == 2);
848        assert_eq!(removed, Some(Box::new([2, 3]) as Box<[i32]>));
849        assert_eq!(list.len(), 2);
850        assert_eq!(list.iter().nth(0), Some(&[1] as &[i32]));
851        assert_eq!(list.iter().nth(1), Some(&[4, 5, 6] as &[i32]));
852    }
853
854    #[test]
855    #[cfg(feature = "nightly")]
856    fn test_unsized_dyn_remove_into_box() {
857        let list = OnceList::<dyn ToString>::new();
858        list.push_unsized(1);
859        list.push_unsized("hello");
860        list.push_unsized(42);
861
862        let mut list = list;
863        let removed = list.remove_into_box(|s| s.to_string() == "hello");
864        assert_eq!(removed.map(|s| s.to_string()), Some("hello".to_string()));
865        assert_eq!(list.len(), 2);
866        assert_eq!(
867            list.iter().nth(0).map(|s| s.to_string()),
868            Some("1".to_string())
869        );
870        assert_eq!(
871            list.iter().nth(1).map(|s| s.to_string()),
872            Some("42".to_string())
873        );
874    }
875
876    #[test]
877    #[cfg(feature = "nightly")]
878    fn test_unsized_slice_remove_as() {
879        let list = OnceList::<[i32]>::new();
880        list.push_unsized([1]);
881        list.push_unsized([2, 3]);
882        list.push_unsized([4, 5, 6]);
883
884        let mut list = list;
885        let removed: Option<[i32; 2]> = unsafe { list.remove_unsized_as(|s| s.try_into().ok()) };
886        assert_eq!(removed, Some([2, 3]));
887        assert_eq!(list.len(), 2);
888        assert_eq!(list.iter().nth(0), Some(&[1] as &[i32]));
889        assert_eq!(list.iter().nth(1), Some(&[4, 5, 6] as &[i32]));
890    }
891}