Skip to main content

clt_database/alloc/collections/
traits.rs

1use super::super::{AllocError, TryReserveError};
2
3pub trait TursoAllocExt {
4    fn new() -> Self;
5}
6
7pub trait TursoTryWithCapacityExt: Sized {
8    fn try_with_capacity_ext(capacity: usize) -> Result<Self, TryReserveError>;
9}
10
11pub trait TursoNewExt<T> {
12    fn new(value: T) -> Self;
13}
14
15pub trait TursoTryNewExt<T>: Sized {
16    fn try_new(value: T) -> Result<Self, AllocError>;
17}
18
19pub trait TursoBoxExt<T>: Sized {
20    fn into_inner(self) -> T;
21}
22
23pub trait TursoVecExt<T>: Sized {
24    fn with_capacity(capacity: usize) -> Self;
25
26    /// Appends an element and returns a reference to it if there is sufficient spare capacity,
27    /// otherwise an error is returned with the element.
28    ///
29    /// Unlike `push`, this method does not reallocate when capacity is exhausted. Callers should
30    /// reserve capacity before using this when insertion must succeed.
31    ///
32    /// Mirrors the unstable standard library implementation:
33    /// <https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#2786>
34    ///
35    /// Takes O(1) time.
36    fn push_within_capacity(&mut self, value: T) -> Result<&mut T, T>;
37
38    fn try_push(&mut self, value: T) -> Result<(), TryReserveError>;
39}
40
41pub trait TursoVecInExt<T, A>: Sized {
42    fn new_in(alloc: A) -> Self;
43    fn with_capacity_in(capacity: usize, alloc: A) -> Self;
44    fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError>;
45}
46
47pub trait TursoHashMapExt<K, V>: Sized {
48    fn try_insert(&mut self, key: K, value: V) -> Result<Option<V>, TryReserveError>;
49}
50
51pub trait TursoHashSetExt<T>: Sized {
52    fn try_insert(&mut self, value: T) -> Result<bool, TryReserveError>;
53}
54
55pub trait TursoVecDequeExt<T>: Sized {
56    fn try_push_back(&mut self, value: T) -> Result<(), TryReserveError>;
57    fn try_push_front(&mut self, value: T) -> Result<(), TryReserveError>;
58}
59
60pub trait TursoBinaryHeapExt<T>: Sized {
61    fn try_push(&mut self, value: T) -> Result<(), TryReserveError>;
62}
63
64/// Conversion from a slice into an allocator-aware `Vec`.
65///
66/// Named `try_to_vec` because the inherent `[T]::to_vec` would always shadow
67/// a trait method called `to_vec`, leaving call sites on the global
68/// allocator.
69pub trait TursoSliceExt<T> {
70    fn try_to_vec(&self) -> Result<crate::alloc::Vec<T>, TryReserveError>;
71}
72
73pub trait TursoFromIterator<T>: Sized {
74    fn try_from_iter<I>(iter: I) -> Result<Self, TryReserveError>
75    where
76        I: IntoIterator<Item = T>;
77
78    fn try_extend<I>(&mut self, iter: I) -> Result<(), TryReserveError>
79    where
80        I: IntoIterator<Item = T>;
81}
82
83#[cfg(nightly)]
84pub trait TursoFromIteratorIn<T, A>: Sized {
85    fn try_from_iter_in<I>(iter: I, alloc: A) -> Result<Self, TryReserveError>
86    where
87        I: IntoIterator<Item = T>;
88}
89
90pub trait TursoIteratorExt: Iterator + Sized {
91    #[inline(always)]
92    fn try_collect<C>(self) -> Result<C, TryReserveError>
93    where
94        C: TursoFromIterator<Self::Item>,
95    {
96        C::try_from_iter(self)
97    }
98
99    #[inline]
100    fn try_unzip<A, B, FromA, FromB>(self) -> Result<(FromA, FromB), TryReserveError>
101    where
102        (FromA, FromB): TursoFromIterator<(A, B)>,
103        Self: Iterator<Item = (A, B)>,
104    {
105        <(FromA, FromB) as TursoFromIterator<(A, B)>>::try_from_iter(self)
106    }
107
108    #[cfg(nightly)]
109    #[inline(always)]
110    fn try_collect_in<C, A>(self, alloc: A) -> Result<C, TryReserveError>
111    where
112        C: TursoFromIteratorIn<Self::Item, A>,
113    {
114        C::try_from_iter_in(self, alloc)
115    }
116}
117
118pub trait TryClone: Sized {
119    type Error;
120
121    fn try_clone(&self) -> Result<Self, Self::Error>;
122}
123
124/// Forward `TryClone` to `Clone` for element types whose clone either cannot
125/// allocate at all (`Copy` primitives) or only allocates through the std
126/// global allocator for now (std-pinned types like `String`). The
127/// `Infallible` error encodes that these clones never return `Err`. The
128/// std-pinned group is a migration marker: once such a type becomes
129/// allocator-aware, give it a real `TryClone<Error = TryReserveError>` impl
130/// and remove it from this list.
131macro_rules! impl_try_clone_via_clone {
132    ($($ty:ty),+ $(,)?) => {
133        $(
134            impl TryClone for $ty {
135                type Error = std::convert::Infallible;
136
137                #[inline(always)]
138                fn try_clone(&self) -> Result<Self, Self::Error> {
139                    Ok(self.clone())
140                }
141            }
142        )+
143    };
144}
145
146pub(crate) use impl_try_clone_via_clone;
147
148impl_try_clone_via_clone!(
149    bool,
150    char,
151    u8,
152    u16,
153    u32,
154    u64,
155    u128,
156    usize,
157    i8,
158    i16,
159    i32,
160    i64,
161    i128,
162    isize,
163    f32,
164    f64,
165    std::string::String,
166);
167
168impl<A, B> TryClone for (A, B)
169where
170    A: TryClone,
171    B: TryClone<Error = A::Error>,
172{
173    type Error = A::Error;
174
175    fn try_clone(&self) -> Result<Self, Self::Error> {
176        Ok((self.0.try_clone()?, self.1.try_clone()?))
177    }
178}
179
180/// `Arc` clones are refcount bumps — no allocation, never fails.
181impl<T> TryClone for crate::sync::Arc<T> {
182    type Error = std::convert::Infallible;
183
184    #[inline(always)]
185    fn try_clone(&self) -> Result<Self, Self::Error> {
186        Ok(self.clone())
187    }
188}
189
190impl<T> TryClone for Option<T>
191where
192    T: TryClone,
193{
194    type Error = T::Error;
195
196    fn try_clone(&self) -> Result<Self, Self::Error> {
197        match self {
198            Some(value) => Ok(Some(value.try_clone()?)),
199            None => Ok(None),
200        }
201    }
202}
203
204impl<T, E> TryClone for Result<T, E>
205where
206    T: TryClone,
207    E: TryClone<Error = T::Error>,
208{
209    type Error = T::Error;
210
211    fn try_clone(&self) -> Result<Self, Self::Error> {
212        match self {
213            Ok(value) => Ok(Ok(value.try_clone()?)),
214            Err(err) => Ok(Err(err.try_clone()?)),
215        }
216    }
217}