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
// devela::data::layout::buffer::impls::linear_vec
#[doc(hidden)]
#[macro_export]
macro_rules! __buffer_linear_impl_vec {
($(#[$impl_attr:meta])* $name:ident, $I:ty, $P:ty) => {
impl<T> Default for $name<T, ::alloc::vec::Vec<T>> {
fn default() -> Self {
Self::new()
}
}
$(#[$impl_attr])*
///
/// Dynamically sized array.
///
/// # Semantics
/// - Logical length is identical to `Vec::len()`.
/// - Capacity may grow dynamically
/// - `push_back` never fails
impl<T> $name<T, ::alloc::vec::Vec<T>> {
/* construct */
/// Creates a buffer from an emtpy `Vec`.
pub const fn new() -> Self { Self::_new(::alloc::vec::Vec::new()) }
/// Creates a buffer from an emtpy `Vec` with at least the given `capacity`.
pub fn with_capacity(capacity: $I) -> Self {
Self::_new(::alloc::vec::Vec::with_capacity(Self::_idx_to_usize(capacity)))
}
/// Creates a buffer from an emtpy `Vec` with at least the given `capacity`.
pub fn with_capacity_prim(capacity: $P) -> Result<Self, $crate::InvalidValue> {
Ok(Self::with_capacity(Self::_prim_to_idx(capacity)?))
}
/* size & capacity */
/// Returns the number of elements currently stored in the buffer.
pub const fn len(&self) -> $I {
Self::_usize_to_idx_sat(self.storage.len()).repr()
}
/// Returns the number of elements currently stored in the buffer.
pub const fn len_prim(&self) -> $P { self.storage.len() as $P }
/// Returns `true` if the buffer contains no elements.
pub const fn is_empty(&self) -> bool { self.storage.is_empty() }
/// Returns the capacity of the underlying `Vec`.
pub const fn capacity(&self) -> $I {
Self::_usize_to_idx_sat(self.storage.capacity()).repr()
}
/// Returns the capacity of the underlying `Vec`.
pub const fn capacity_prim(&self) -> $P { self.storage.capacity() as $P }
/// Returns the additional elements that can be pushed without reallocating.
pub const fn remaining_capacity(&self) -> $I {
Self::_usize_to_idx_sat(self.storage.capacity() - self.storage.len()).repr()
}
/// Returns the additional elements that can be pushed without reallocating.
pub const fn remaining_capacity_prim(&self) -> $P {
(self.storage.capacity() - self.storage.len()) as $P
}
/// Returns `true` if the current allocation has no remaining capacity.
///
/// Pushing another element may reallocate.
pub const fn is_full(&self) -> bool { self.storage.len() == self.storage.capacity() }
/* logical range control */
/// Sets the logical length to zero.
///
/// Does not drop elements.
pub fn clear(&mut self) { self.storage.clear() }
/// Sets the logical length to `min(new_len, len)`.
///
/// If `new_len >= len`, this is a no-op.
pub fn truncate(&mut self, new_len: $I) {
self.storage.truncate(Self::_idx_to_usize(new_len));
}
/// Primitive-index variant of [`truncate`][Self::truncate],
pub fn truncate_prim(&mut self, new_len: $P) -> Result<(), $crate::InvalidValue> {
self.truncate($crate::unwrap![ok? Self::_prim_to_idx(new_len)]);
Ok(())
}
/* push */
/// Removes and returns a value from the back of the buffer.
pub fn push_back(&mut self, value: T) { self.storage.push(value); }
/// Appends elements cloned from `src` to the back of the buffer.
///
/// Returns the number of elements appended, which is always `src.len()`.
///
/// This may reallocate the underlying storage.
pub fn push_slice(&mut self, src: &[T]) -> usize where T: Clone {
self.storage.extend_from_slice(src);
src.len()
}
/* pop */
/// Removes and returns a value from the back of the buffer.
pub fn pop_back(&mut self) -> Option<T> { self.storage.pop() }
/* peek */
/// Returns a shared reference to the last element without removing it.
pub fn peek_back(&self) -> Option<&T> { self.storage.last() }
/// Returns an exclusive reference to the last element without removing it.
pub fn peek_mut_back(&mut self) -> Option<&mut T> { self.storage.last_mut() }
/* get */
/// Returns a shared reference to the element at `index`, or `None` if out of bounds.
pub fn get(&self, index: $I) -> Option<&T> {
let idx = Self::_idx_to_usize(index);
self.storage.get(idx)
}
/// Returns an exclusive reference to the element at `index`,
/// or `None` if out of bounds.
pub fn get_mut(&mut self, index: $I) -> Option<&mut T> {
let idx = Self::_idx_to_usize(index);
self.storage.get_mut(idx)
}
/* take */
/// Takes the value at `index`, replacing it with `value`.
pub fn take_with(&mut self, index: $I, other: T) -> Option<T> {
let idx = Self::_idx_to_usize(index);
if idx >= self.storage.len() { return None; }
Some($crate::Mem::replace(&mut self.storage[idx], other))
}
/// Takes the value at `index`, replacing it with `T::default()`.
pub fn take_default(&mut self, index: $I) -> Option<T> where T: Default {
self.take_with(index, T::default())
}
/// Takes the value at `index`, replacing it with `T::INIT`.
pub fn take_init(&mut self, index: $I) -> Option<T> where T: $crate::ConstInit {
self.take_with(index, T::INIT)
}
/* views */
/// Returns the active logical range as a slice.
pub fn as_slice(&self) -> &[T] { &self.storage }
/// Returns the active logical range as an exclusive slice.
pub fn as_mut_slice(&mut self) -> &mut [T] { &mut self.storage }
$crate::buffer_linear!(%common_iter_visit $name, $I, $P);
}
};
}