standard_lib/collections/circular/stack/
circ_stack.rs1use std::{array::TryFromSliceError, mem::{self, MaybeUninit}, ops::{Index, IndexMut}};
2
3use super::{Iter, IterMut};
4
5const MAX_SIZE: usize = isize::MAX as usize;
6
7const fn check_size(n: usize) {
8 if !(n <= MAX_SIZE) {
{ ::core::panicking::panic_fmt(format_args!("N exceeds maximum size!")); }
};assert!(n <= MAX_SIZE, "N exceeds maximum size!");
9}
10
11#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug, const N : usize> ::core::fmt::Debug for
CircStack<T, N> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "CircStack",
"buffer", &self.buffer, "tail", &&self.tail)
}
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone, const N : usize> ::core::clone::Clone for
CircStack<T, N> {
#[inline]
fn clone(&self) -> CircStack<T, N> {
CircStack {
buffer: ::core::clone::Clone::clone(&self.buffer),
tail: ::core::clone::Clone::clone(&self.tail),
}
}
}Clone, #[automatically_derived]
impl<T: ::core::hash::Hash, const N : usize> ::core::hash::Hash for
CircStack<T, N> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.buffer, state);
::core::hash::Hash::hash(&self.tail, state)
}
}Hash, #[automatically_derived]
impl<T: ::core::cmp::PartialEq, const N : usize> ::core::cmp::PartialEq for
CircStack<T, N> {
#[inline]
fn eq(&self, other: &CircStack<T, N>) -> bool {
self.buffer == other.buffer && self.tail == other.tail
}
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq, const N : usize> ::core::cmp::Eq for CircStack<T, N>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<[T; N]>;
let _: ::core::cmp::AssertParamIsEq<usize>;
}
}Eq, #[automatically_derived]
impl<T: ::core::cmp::PartialOrd, const N : usize> ::core::cmp::PartialOrd for
CircStack<T, N> {
#[inline]
fn partial_cmp(&self, other: &CircStack<T, N>)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.buffer,
&other.buffer) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.tail, &other.tail),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl<T: ::core::cmp::Ord, const N : usize> ::core::cmp::Ord for
CircStack<T, N> {
#[inline]
fn cmp(&self, other: &CircStack<T, N>) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.buffer, &other.buffer) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.tail, &other.tail),
cmp => cmp,
}
}
}Ord)]
12pub struct CircStack<T, const N: usize> {
13 pub(crate) buffer: [T; N],
14 pub(crate) tail: usize,
15}
16
17pub(crate) const fn increment<const N: usize>(index: usize) -> usize {
18 (index + 1) % N
20}
21
22pub(crate) const fn sub_wrapping<const N: usize>(index: usize, diff: usize) -> usize {
23 if index >= N {
24 { ::core::panicking::panic_fmt(format_args!("TODO")); }panic!("TODO")
25 }
26
27 unsafe {
28 index.checked_signed_diff(diff).unwrap_unchecked()
31 }.rem_euclid(N as isize) as usize
32}
33
34impl<T, const N: usize> CircStack<T, N> {
35 pub(crate) const fn increment(&mut self) {
36 self.tail = increment::<N>(self.tail)
37 }
38
39 pub(crate) const fn decrement(&mut self) {
40 self.tail = sub_wrapping::<N>(self.tail, 1);
41 }
42
43 pub(crate) const fn translate_index(&self, index: usize) -> usize {
44 sub_wrapping::<N>(self.tail, index)
45 }
46
47 pub const fn new(buffer: [T; N], tail: usize) -> CircStack<T, N> {
48 const { check_size(N) };
49
50 CircStack {
51 buffer,
52 tail
53 }
54 }
55
56 pub const fn new_uninit() -> CircStack<MaybeUninit<T>, N> {
57 CircStack::new(
58 [const { MaybeUninit::uninit() }; N],
59 0
60 )
61 }
62
63 pub fn push(&mut self, value: T) {
64 self.increment();
65 self.buffer[self.tail] = value;
66 }
67
68 pub const fn pop_with_replacement(&mut self, replacement: T) -> T {
69 let value = mem::replace(&mut self.buffer[self.tail], replacement);
70 self.decrement();
71 value
72 }
73
74 pub const fn as_array(&self) -> &[T; N] {
75 &self.buffer
76 }
77
78 pub const fn as_array_mut(&mut self) -> &mut [T; N] {
79 &mut self.buffer
80 }
81
82 pub fn forget_init(self) -> CircStack<MaybeUninit<T>, N> {
83 let CircStack { buffer, tail } = self;
84
85 CircStack {
86 buffer: buffer.map(MaybeUninit::new),
87 tail
88 }
89 }
90
91 pub const fn rotate(&mut self, offset: isize) {
93 if offset >= N as isize || offset <= -(N as isize) {
94 { ::core::panicking::panic_fmt(format_args!("TODO")); }panic!("TODO")
95 }
96
97 self.tail = (self.tail as isize + offset).rem_euclid(N as isize) as usize;
98 }
99
100 pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
101 self.into_iter()
102 }
103
104 pub fn iter(&self) -> Iter<'_, T, N> {
105 self.into_iter()
106 }
107}
108
109impl<T: Copy, const N: usize> CircStack<T, N> {
110 pub const fn repeat_item(item: T) -> CircStack<T, N> {
111 CircStack::new(
112 [item; N],
113 0
114 )
115 }
116
117 pub const fn pop_copy(&mut self) -> T {
118 let value = self.buffer[self.tail];
119 self.decrement();
120 value
121 }
122
123 pub const fn last(&self) -> &T {
124 &self.buffer[self.tail]
125 }
126}
127
128impl<T: Default, const N: usize> CircStack<T, N> {
129 pub fn pop_with_default(&mut self) -> T {
130 self.pop_with_replacement(T::default())
131 }
132}
133
134impl<T, const N: usize> CircStack<MaybeUninit<T>, N> {
135 pub const fn transpose(self) -> MaybeUninit<CircStack<T, N>> {
136 unsafe { mem::transmute_copy(&MaybeUninit::new(self)) }
140 }
141
142 pub const fn transpose_mut(&mut self) -> &mut MaybeUninit<CircStack<T, N>> {
143 unsafe { mem::transmute(self) }
144 }
145
146 pub const fn transpose_ref(&self) -> &MaybeUninit<CircStack<T, N>> {
147 unsafe { mem::transmute(self) }
148 }
149
150 pub const unsafe fn assume_init(self) -> CircStack<T, N> {
151 unsafe { self.transpose().assume_init() }
152 }
153
154 pub const unsafe fn assume_init_mut(&mut self) -> &mut CircStack<T, N> {
155 unsafe { self.transpose_mut().assume_init_mut() }
156 }
157
158 pub const unsafe fn assume_init_ref(&self) -> &CircStack<T, N> {
159 unsafe { self.transpose_ref().assume_init_ref() }
160 }
161}
162
163impl<T, const N: usize> CircStack<Option<T>, N> {
164 pub fn transpose(self) -> Option<CircStack<T, N>> {
165 let CircStack { buffer, tail } = self;
166
167 Some(CircStack {
168 buffer: buffer.transpose()?,
169 tail,
170 })
171 }
172}
173
174impl<T: Default, const N: usize> Default for CircStack<T, N> {
175 fn default() -> CircStack<T, N> {
176 CircStack::new(
177 [(); N].map(|_| T::default()),
178 0
179 )
180 }
181}
182
183impl<T: Copy, const N: usize> TryFrom<&[T]> for CircStack<T, N> {
184 type Error = TryFromSliceError;
185
186 fn try_from(value: &[T]) -> Result<Self, Self::Error> {
187 Ok(CircStack::new(
188 <[T; N]>::try_from(value)?,
189 0
190 ))
191 }
192}
193
194impl<T, const N: usize> From<[T; N]> for CircStack<T, N> {
195 fn from(buffer: [T; N]) -> Self {
196 CircStack::new(buffer, 0)
197 }
198}
199
200impl<T, const N: usize> Index<usize> for CircStack<T, N> {
203 type Output = T;
204
205 fn index(&self, index: usize) -> &Self::Output {
206 &self.buffer[self.translate_index(index)]
207 }
208}
209
210impl<T, const N: usize> IndexMut<usize> for CircStack<T, N> {
211 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
212 &mut self.buffer[self.translate_index(index)]
213 }
214}