1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
use crate::{
    misc::BufferTooSmall, wrapper::Array,
    std::{
        fmt::Debug, ops::RangeBounds,
        slice::{ Iter as SliceIter, IterMut as SliceIterMut }
    }
};
#[cfg(feature = "std")]
use crate::misc::WillPanic;


/// A trait for referencable linear array types
pub trait ArrayRef<T> {
    /// The underlying elements as slice
    fn as_slice(&self) -> &[T];
    /// The length of the wrapped elements
    fn len(&self) -> usize;
    /// Whether `self` is empty or not
    fn is_empty(&self) -> bool;

    /// Gets an element
    fn get(&self, index: usize) -> Option<&T>;
    /// Gets a subrange
    fn get_n<Range>(&self, range: Range) -> Option<Array<&[T]>> where Range: RangeBounds<usize>;

    /// Returns a reference to the first element
    fn first(&self) -> Option<&T>;
    /// Returns a reference to the last element
    fn last(&self) -> Option<&T>;

    /// Returns an iterator that references the elements
    fn iter(&self) -> SliceIter<T>;

    /// Clones `self` to `target`
    fn clone_to<Target>(&self, target: &mut Target) -> Result<(), BufferTooSmall> where Target: ArrayMut<T>, T: Clone;
}


/// A trait for mutably referencable linear array types
pub trait ArrayMut<T>: ArrayRef<T> {
    /// The underlying element as mutable slice
    fn as_slice_mut(&mut self) -> &mut [T];

    /// Gets a mutable reference to an element
    fn get_mut(&mut self, index: usize) -> Option<&mut T>;
    /// Gets a mutable subrange
    fn get_n_mut<Range>(&mut self, range: Range) -> Option<Array<&mut [T]>> where Range: RangeBounds<usize>;

    /// Returns a mutable reference to the first element
    fn first_mut(&mut self) -> Option<&mut T>;
    /// Returns a mutable reference to the last element
    fn last_mut(&mut self) -> Option<&mut T>;

    /// Returns an iterator that mutably references the elements
    fn iter_mut(&mut self) -> SliceIterMut<T>;

    /// Rotates the elements left by `count` fields
    fn rotate_left(&mut self, count: usize);
    /// Rotates the elements right by `count` fields
    fn rotate_right(&mut self, count: usize);
    /// Reverses the order of elements in the slice
    fn reverse(&mut self);
}


/// A trait for allocatable/resizeable linear array types
pub trait ArrayAlloc<T>: ArrayMut<T> + Sized {
    /// An alloc related error
    type Error: Debug;
    
    /// Creates a newly allocated instance of `Self`
    fn alloc_new() -> Result<Self, Self::Error>;
    /// Clones `source` into a newly allocated instance of `Self`
    fn alloc_clone<Source>(source: &Source) -> Result<Self, Self::Error> where Source: ArrayRef<T>, T: Clone;

    /// Grows `self` to the given capacity if the current length is smaller than `len` and inits new elements using `init`
    fn grow_with(&mut self, len: usize, init: impl FnMut() -> T) -> Result<(), Self::Error>;
    /// Grows `self` to the given capacity if the current length is smaller than `len` and inits new elements using
    /// `Default`
    fn grow(&mut self, len: usize) -> Result<(), Self::Error> where T: Default;
    /// Shrinks `self` to the given capacity if the current length is larger than `len`
    fn shrink(&mut self, len: usize) -> Result<(), Self::Error>;

    /// Pushes an `element` to the front of `self`
    fn push_front(&mut self, element: T) -> Result<(), Self::Error>;
    /// Pushes some `elements` to the front of `self`
    fn push_n_front<Source>(&mut self, elements: &Source) -> Result<(), Self::Error>
        where Source: ArrayRef<T>, T: Clone;
    /// Pushes an `element` to the front of `self`
    fn push_back(&mut self, element: T) -> Result<(), Self::Error>;
    /// Pushes some `elements` to the front of `self`
    fn push_n_back<Source>(&mut self, elements: &Source) -> Result<(), Self::Error> where Source: ArrayRef<T>, T: Clone;

    /// Pops an `element` from the front of `self`
    fn pop_front(&mut self) -> Result<Option<T>, Self::Error>;
    /// Pops multiple `elements` from the front of `self`
    fn pop_n_front(&mut self, len: usize) -> Result<Option<Self>, Self::Error>;
    /// Pops an `element` from the back of `self`
    fn pop_back(&mut self) -> Result<Option<T>, Self::Error>;
    /// Pops multiple `elements` from the back of `self`
    fn pop_n_back(&mut self, len: usize) -> Result<Option<Self>, Self::Error>;
}


/// An infallible/panicking variant of `ArrayAlloc`
///
///  - Note: This trait adopts Rust's "panic on allocation failure" policy. While this trait reintroduces a panic cause,
///    it's usually much more convenient to use – especially for `std`-types which use `WillPanic` anyway.
pub trait ArrayAllocPanic<T>: ArrayMut<T> + Sized {
    /// Creates a newly allocated instance of `Self`
    fn alloc_new() -> Self;
    /// Clones `source` into a newly allocated instance of `Self`
    fn alloc_clone<Source>(source: &Source) -> Self where Source: ArrayRef<T>, T: Clone;

    /// Grows `self` to the given capacity if the current length is smaller than `len` and inits new elements using `init`
    fn grow_with(&mut self, len: usize, init: impl FnMut() -> T);
    /// Grows `self` to the given capacity if the current length is smaller than `len` and inits new elements using
    /// `Default`
    fn grow(&mut self, len: usize) where T: Default;
    /// Shrinks `self` to the given capacity if the current length is larger than `len`
    fn shrink(&mut self, len: usize);

    /// Pushes an `element` to the front of `self`
    fn push_front(&mut self, element: T);
    /// Pushes some `elements` to the front of `self`
    fn push_n_front<Source>(&mut self, elements: &Source) where Source: ArrayRef<T>, T: Clone;
    /// Pushes an `element` to the front of `self`
    fn push_back(&mut self, element: T);
    /// Pushes some `elements` to the front of `self`
    fn push_n_back<Source>(&mut self, elements: &Source) where Source: ArrayRef<T>, T: Clone;

    /// Pops an `element` from the front of `self`
    fn pop_front(&mut self) -> Option<T>;
    /// Pops multiple `elements` from the front of `self`
    fn pop_n_front(&mut self, len: usize) -> Option<Self>;
    /// Pops an `element` from the back of `self`
    fn pop_back(&mut self) -> Option<T>;
    /// Pops multiple `elements` from the back of `self`
    fn pop_n_back(&mut self, len: usize) -> Option<Self>;
}
impl<T, Array> ArrayAllocPanic<T> for Array where Array: ArrayAlloc<T> {
    fn alloc_new() -> Self {
        <Self as ArrayAlloc<T>>::alloc_new().expect("Allocation error")
    }
    fn alloc_clone<Source>(elements: &Source) -> Self where Source: ArrayRef<T>, T: Clone {
        <Self as ArrayAlloc<T>>::alloc_clone(elements).expect("Allocation error")
    }

    fn grow_with(&mut self, len: usize, init: impl FnMut() -> T) {
        <Self as ArrayAlloc<T>>::grow_with(self, len, init).expect("Allocation error")
    }
    fn grow(&mut self, len: usize) where T: Default {
        <Self as ArrayAlloc<T>>::grow(self, len).expect("Allocation error")
    }
    fn shrink(&mut self, len: usize) {
        <Self as ArrayAlloc<T>>::shrink(self, len).expect("Allocation error")
    }

    fn push_front(&mut self, element: T) {
        <Self as ArrayAlloc<T>>::push_front(self, element).expect("Allocation error")
    }
    fn push_n_front<Source>(&mut self, elements: &Source) where Source: ArrayRef<T>, T: Clone {
        <Self as ArrayAlloc<T>>::push_n_front(self, elements).expect("Allocation error")
    }
    fn push_back(&mut self, element: T) {
        <Self as ArrayAlloc<T>>::push_back(self, element).expect("Allocation error")
    }
    fn push_n_back<Source>(&mut self, elements: &Source) where Source: ArrayRef<T>, T: Clone {
        <Self as ArrayAlloc<T>>::push_n_back(self, elements).expect("Allocation error")
    }

    fn pop_front(&mut self) -> Option<T> {
        <Self as ArrayAlloc<T>>::pop_front(self).expect("Allocation error")
    }
    fn pop_n_front(&mut self, len: usize) -> Option<Self> {
        <Self as ArrayAlloc<T>>::pop_n_front(self, len).expect("Allocation error")
    }
    fn pop_back(&mut self) -> Option<T> {
        <Self as ArrayAlloc<T>>::pop_back(self).expect("Allocation error")
    }
    fn pop_n_back(&mut self, len: usize) -> Option<Self> {
        <Self as ArrayAlloc<T>>::pop_n_back(self, len).expect("Allocation error")
    }
}


/// A trait for types that can perform stack-like memory allocation
pub trait CanAlloc<T>: Sized {
    /// An allocation related error
    type Error: Debug;

    /// Creates a new potentially allocated instance of `Self`
    fn alloc_new() -> Result<Self, Self::Error>;

    /// Pushes an `element` to the end of `self`
    fn push(&mut self, element: T) -> Result<(), Self::Error>;
    /// Pops an `element` from the end of `self` if any
    fn pop(&mut self) -> Result<Option<T>, Self::Error>;
}
#[cfg(feature = "std")]
impl<T> CanAlloc<T> for Vec<T> {
    type Error = WillPanic;

    fn alloc_new() -> Result<Self, Self::Error> {
        Ok(Self::new())
    }

    fn push(&mut self, element: T) -> Result<(), Self::Error> {
        Ok(self.push(element))
    }
    fn pop(&mut self) -> Result<Option<T>, Self::Error> {
        Ok(self.pop())
    }
}