cl_structures/stack.rs
1//! A contiguous collection with constant capacity.
2//!
3//! Since the capacity of a [Stack] may be [*known at compile time*](Sized),
4//! it may live on the call stack.
5//!
6//!
7//! # Examples
8//!
9//! Unlike a [Vec], the [Stack] doesn't grow when it reaches capacity.
10//! ```should_panic
11//! # use cl_structures::stack::*;
12//! let mut v = stack![1];
13//! v.push("This should work");
14//! v.push("This will panic!");
15//! ```
16//! To get around this limitation, the methods [try_push](Stack::try_push) and
17//! [try_insert](Stack::try_insert) are provided:
18//! ```
19//! # use cl_structures::stack::*;
20//! let mut v = stack![1];
21//! v.push("This should work");
22//! v.try_push("This should produce an err").unwrap_err();
23//! ```
24//!
25//! As the name suggests, a [Stack] enforces a stack discipline:
26//! ```
27//! # use cl_structures::stack::*;
28//! let mut v = stack![100];
29//!
30//! assert_eq!(100, v.capacity());
31//! assert_eq!(0, v.len());
32//!
33//! // Elements are pushed one at a time onto the stack
34//! v.push("foo");
35//! v.push("bar");
36//! assert_eq!(2, v.len());
37//!
38//! // The stack can be used anywhere a slice is expected
39//! assert_eq!(Some(&"foo"), v.get(0));
40//! assert_eq!(Some(&"bar"), v.last());
41//!
42//! // Elements are popped from the stack in reverse order
43//! assert_eq!(Some("bar"), v.pop());
44//! assert_eq!(Some("foo"), v.pop());
45//! assert_eq!(None, v.pop());
46//! ```
47
48// yar har! here there be unsafe code! Tread carefully.
49
50use core::slice;
51use std::{
52 fmt::Debug,
53 marker::PhantomData,
54 mem::{ManuallyDrop, MaybeUninit},
55 ops::{Deref, DerefMut},
56 ptr,
57};
58
59/// Creates a [`stack`] containing the arguments
60///
61/// # Examples
62///
63/// Creates a *full* [`Stack`] containing a list of elements
64/// ```
65/// # use cl_structures::stack::stack;
66/// let mut v = stack![1, 2, 3];
67///
68/// assert_eq!(Some(3), v.pop());
69/// assert_eq!(Some(2), v.pop());
70/// assert_eq!(Some(1), v.pop());
71/// assert_eq!(None, v.pop());
72/// ```
73///
74/// Creates a *full* [`Stack`] from a given element and size
75/// ```
76/// # use cl_structures::stack::stack;
77/// let mut v = stack![1; 2];
78///
79/// assert_eq!(Some(1), v.pop());
80/// assert_eq!(Some(1), v.pop());
81/// assert_eq!(None, v.pop());
82/// ```
83///
84/// Creates an *empty* [`Stack`] from a given size
85/// ```
86/// # use cl_structures::stack::{Stack, stack};
87/// let mut v = stack![10];
88///
89/// assert_eq!(0, v.len());
90/// assert_eq!(10, v.capacity());
91///
92/// v.push(10);
93/// assert_eq!(Some(&10), v.last());
94/// ```
95pub macro stack {
96 ($capacity:literal) => {
97 Stack::<_, $capacity>::new()
98 },
99 ($value:expr ; $count:literal) => {{
100 let mut stack: Stack<_, $count> = Stack::new();
101 for _ in 0..$count {
102 stack.push($value)
103 }
104 stack
105 }},
106 ($value:expr ; $count:literal ; $capacity:literal) => {{
107 let mut stack: Stack<_, $capacity> = Stack::new();
108 for _ in 0..$count {
109 stack.push($value)
110 }
111 stack
112 }},
113 ($($values:expr),* $(,)?) => {
114 Stack::from([$($values),*])
115 }
116}
117
118/// A contiguous collection with constant capacity
119pub struct Stack<T, const N: usize> {
120 _data: PhantomData<T>,
121 buf: [MaybeUninit<T>; N],
122 len: usize,
123}
124
125impl<T: Clone, const N: usize> Clone for Stack<T, N> {
126 fn clone(&self) -> Self {
127 let mut new = Self::new();
128 for value in self.iter() {
129 new.push(value.clone())
130 }
131 new
132 }
133}
134
135impl<T: Debug, const N: usize> Debug for Stack<T, N> {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 f.debug_list().entries(self.iter()).finish()
138 }
139}
140
141impl<T, const N: usize> Default for Stack<T, N> {
142 fn default() -> Self {
143 Self::new()
144 }
145}
146
147impl<T, const N: usize> Deref for Stack<T, N> {
148 type Target = [T];
149
150 #[inline]
151 fn deref(&self) -> &Self::Target {
152 self.as_slice()
153 }
154}
155
156impl<T, const N: usize> DerefMut for Stack<T, N> {
157 #[inline]
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 self.as_mut_slice()
160 }
161}
162
163// requires dropck-eyepatch for elements with contravariant lifetimes
164unsafe impl<#[may_dangle] T, const N: usize> Drop for Stack<T, N> {
165 #[inline]
166 fn drop(&mut self) {
167 // Safety: Elements in [0..self.len] are initialized
168 if std::mem::needs_drop::<T>() {
169 unsafe { core::ptr::drop_in_place(self.as_mut_slice()) };
170 }
171 }
172}
173
174impl<T, const N: usize> Extend<T> for Stack<T, N> {
175 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
176 for value in iter {
177 self.push(value)
178 }
179 }
180}
181
182impl<T, const N: usize> From<[T; N]> for Stack<T, N> {
183 fn from(value: [T; N]) -> Self {
184 let value = ManuallyDrop::new(value);
185 if std::mem::size_of::<[T; N]>() == 0 {
186 // Safety: since [T; N] is zero-sized, and there are no other fields,
187 // it should be okay to interpret N as Self
188 unsafe { ptr::read(&N as *const _ as *const _) }
189 } else {
190 // Safety:
191 // - `value` is ManuallyDrop, so its destructor won't run
192 // - All elements are assumed to be initialized (so len is N)
193 Self {
194 buf: unsafe { ptr::read(&value as *const _ as *const _) },
195 len: N,
196 ..Default::default()
197 }
198 }
199 }
200}
201
202impl<T, const N: usize> Stack<T, N> {
203 /// Constructs a new, empty [Stack]
204 ///
205 /// # Examples
206 ///
207 /// ```
208 /// # use cl_structures::stack::Stack;
209 /// let mut v: Stack<_, 3> = Stack::new();
210 ///
211 /// v.try_push(1).unwrap();
212 /// v.try_push(2).unwrap();
213 /// v.try_push(3).unwrap();
214 /// // Trying to push a 4th element will fail, and return the failed element
215 /// assert_eq!(4, v.try_push(4).unwrap_err());
216 ///
217 /// assert_eq!(Some(3), v.pop());
218 /// ```
219 pub const fn new() -> Self {
220 Self { buf: [const { MaybeUninit::uninit() }; N], len: 0, _data: PhantomData }
221 }
222
223 /// Constructs a new [Stack] from an array of [`MaybeUninit<T>`] and an initialized length
224 ///
225 /// # Safety
226 ///
227 /// - Elements from `0..len` must be initialized
228 /// - len must not exceed the length of the array
229 ///
230 /// # Examples
231 ///
232 /// ```
233 /// # use cl_structures::stack::Stack;
234 /// # use core::mem::MaybeUninit;
235 /// let mut v = unsafe { Stack::from_raw_parts([MaybeUninit::new(100)], 1) };
236 ///
237 /// assert_eq!(1, v.len());
238 /// assert_eq!(1, v.capacity());
239 /// assert_eq!(Some(100), v.pop());
240 /// assert_eq!(None, v.pop());
241 /// ```
242 pub const unsafe fn from_raw_parts(buf: [MaybeUninit<T>; N], len: usize) -> Self {
243 Self { buf, len, _data: PhantomData }
244 }
245
246 /// Converts a [Stack] into an array of [`MaybeUninit<T>`] and the initialized length
247 ///
248 /// # Examples
249 ///
250 /// ```
251 /// # use cl_structures::stack::Stack;
252 /// let mut v: Stack<_, 10> = Stack::new();
253 /// v.push(0);
254 /// v.push(1);
255 ///
256 /// let (buf, len) = v.into_raw_parts();
257 ///
258 /// assert_eq!(0, unsafe { buf[0].assume_init() });
259 /// assert_eq!(1, unsafe { buf[1].assume_init() });
260 /// assert_eq!(2, len);
261 /// ```
262 #[inline]
263 pub fn into_raw_parts(self) -> ([MaybeUninit<T>; N], usize) {
264 let this = ManuallyDrop::new(self);
265 // Safety: since
266 (unsafe { ptr::read(&this.buf) }, this.len)
267 }
268
269 /// Returns a raw pointer to the stack's buffer
270 pub const fn as_ptr(&self) -> *const T {
271 self.buf.as_ptr().cast()
272 }
273
274 /// Returns an unsafe mutable pointer to the stack's buffer
275 pub const fn as_mut_ptr(&mut self) -> *mut T {
276 self.buf.as_mut_ptr().cast()
277 }
278
279 /// Extracts a slice containing the entire vector
280 pub const fn as_slice(&self) -> &[T] {
281 // Safety:
282 // - We have ensured all elements from 0 to len have been initialized
283 // - self.elem[0] came from a reference, and so is aligned to T
284 // unsafe { &*(&self.buf[0..self.len] as *const [_] as *const [T]) }
285 unsafe { slice::from_raw_parts(self.buf.as_ptr().cast(), self.len) }
286 }
287
288 /// Extracts a mutable slice containing the entire vector
289 pub const fn as_mut_slice(&mut self) -> &mut [T] {
290 // Safety:
291 // - See Stack::as_slice
292 unsafe { slice::from_raw_parts_mut(self.buf.as_mut_ptr().cast(), self.len) }
293 }
294
295 /// Returns the total number of elements the stack can hold
296 pub const fn capacity(&self) -> usize {
297 N
298 }
299
300 /// Moves an existing stack into an allocation of a (potentially) different size,
301 /// truncating if necessary.
302 ///
303 /// This can be used to easily construct a half-empty stack
304 ///
305 /// # Examples
306 ///
307 /// You can grow a stack to fit more elements
308 /// ```
309 /// # use cl_structures::stack::Stack;
310 /// let v = Stack::from([0, 1, 2, 3, 4]);
311 /// assert_eq!(5, v.capacity());
312 ///
313 /// let mut v = v.resize::<10>();
314 /// assert_eq!(10, v.capacity());
315 ///
316 /// v.push(5);
317 /// ```
318 ///
319 /// You can truncate a stack, dropping elements off the end
320 /// ```
321 /// # use cl_structures::stack::Stack;
322 /// let v = Stack::from([0, 1, 2, 3, 4, 5, 6, 7]);
323 /// assert_eq!(8, v.capacity());
324 ///
325 /// let v = v.resize::<5>();
326 /// assert_eq!(5, v.capacity());
327 /// ```
328 pub fn resize<const M: usize>(mut self) -> Stack<T, M> {
329 // Drop elements until new length is reached
330 while self.len > M {
331 drop(self.pop());
332 }
333 let (old, len) = self.into_raw_parts();
334 let mut new: Stack<T, M> = Stack::new();
335
336 // Safety:
337 // - new and old are separate allocations
338 // - len <= M
339 unsafe {
340 ptr::copy_nonoverlapping(old.as_ptr(), new.buf.as_mut_ptr(), len);
341 }
342
343 new.len = len;
344 new
345 }
346
347 /// Push a new element onto the end of the stack
348 ///
349 /// # May Panic
350 ///
351 /// Panics if the new length exceeds capacity
352 ///
353 /// # Examples
354 ///
355 /// ```
356 /// # use cl_structures::stack::Stack;
357 /// let mut v: Stack<_, 4> = Stack::new();
358 ///
359 /// v.push(0);
360 /// v.push(1);
361 /// v.push(2);
362 /// v.push(3);
363 /// assert_eq!(&[0, 1, 2, 3], v.as_slice());
364 /// ```
365 pub const fn push(&mut self, value: T) {
366 if self.len >= N {
367 panic!("Attempted to push into full stack")
368 }
369 // Safety: len is confirmed to be less than capacity
370 unsafe { self.push_unchecked(value) };
371 }
372
373 /// Push a new element onto the end of the stack
374 ///
375 /// Returns [`Err(value)`](Result::Err) if the new length would exceed capacity
376 pub const fn try_push(&mut self, value: T) -> Result<(), T> {
377 if self.len >= N {
378 return Err(value);
379 }
380 // Safety: len is confirmed to be less than capacity
381 unsafe { self.push_unchecked(value) };
382 Ok(())
383 }
384
385 /// Push a new element onto the end of the stack, without checking capacity
386 ///
387 /// # Safety
388 ///
389 /// len after push must not exceed capacity N
390 #[inline]
391 const unsafe fn push_unchecked(&mut self, value: T) {
392 unsafe {
393 // self.buf.get_unchecked_mut(self.len).write(value); // TODO: This is non-const
394 ptr::write(self.as_mut_ptr().add(self.len), value)
395 }
396 self.len += 1; // post inc
397 }
398
399 /// Pops the last element off the end of the stack, and returns it
400 ///
401 /// Returns None if the stack is empty
402 ///
403 /// # Examples
404 ///
405 /// ```
406 /// # use cl_structures::stack::Stack;
407 /// let mut v = Stack::from([0, 1, 2, 3]);
408 ///
409 /// assert_eq!(Some(3), v.pop());
410 /// assert_eq!(Some(2), v.pop());
411 /// assert_eq!(Some(1), v.pop());
412 /// assert_eq!(Some(0), v.pop());
413 /// assert_eq!(None, v.pop());
414 /// ```
415 pub const fn pop(&mut self) -> Option<T> {
416 if self.len == 0 {
417 None
418 } else {
419 self.len -= 1;
420 // Safety: MaybeUninit<T> implies ManuallyDrop<T>,
421 // therefore should not get dropped twice
422 // Some(unsafe { self.buf.get_unchecked_mut(self.len).assume_init_read() })
423 Some(unsafe { ptr::read(self.as_ptr().add(self.len).cast()) })
424 }
425 }
426
427 /// Removes and returns the element at the given index,
428 /// shifting other elements toward the start
429 ///
430 /// # Examples
431 ///
432 /// ```
433 /// # use cl_structures::stack::Stack;
434 /// let mut v = Stack::from([0, 1, 2, 3, 4]);
435 ///
436 /// assert_eq!(2, v.remove(2));
437 /// assert_eq!(&[0, 1, 3, 4], v.as_slice());
438 /// ```
439 pub fn remove(&mut self, index: usize) -> T {
440 if index >= self.len {
441 panic!("Index {index} exceeded length {}", self.len)
442 }
443 let len = self.len - 1;
444 let base = self.as_mut_ptr();
445 let out = unsafe { ptr::read(base.add(index)) };
446
447 unsafe { ptr::copy(base.add(index + 1), base.add(index), len - index) };
448 self.len = len;
449 out
450 }
451
452 /// Removes and returns the element at the given index,
453 /// swapping it with the last element.
454 ///
455 /// # May Panic
456 ///
457 /// Panics if `index >= len`.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// # use cl_structures::stack::Stack;
463 /// let mut v = Stack::from([0, 1, 2, 3, 4]);
464 ///
465 /// assert_eq!(2, v.swap_remove(2));
466 ///
467 /// assert_eq!(&[0, 1, 4, 3], v.as_slice());
468 /// ```
469 pub fn swap_remove(&mut self, index: usize) -> T {
470 if index >= self.len {
471 panic!("Index {index} exceeds length {}", self.len);
472 }
473 let len = self.len - 1;
474 let ptr = self.as_mut_ptr();
475 let out = unsafe { ptr::read(ptr.add(index)) };
476
477 unsafe { ptr::copy(ptr.add(len), ptr.add(index), 1) };
478 self.len = len;
479 out
480 }
481
482 /// Inserts an element at position `index` in the stack,
483 /// shifting all elements after it to the right.
484 ///
485 /// # May Panic
486 ///
487 /// Panics if `index > len` or [`self.is_full()`](Stack::is_full)
488 ///
489 /// # Examples
490 ///
491 /// ```
492 /// # use cl_structures::stack::Stack;
493 /// let mut v = Stack::from([0, 1, 2, 3, 4]).resize::<6>();
494 ///
495 /// v.insert(3, 0xbeef);
496 /// assert_eq!(&[0, 1, 2, 0xbeef, 3, 4], v.as_slice());
497 /// ```
498 pub fn insert(&mut self, index: usize, data: T) {
499 if index > self.len {
500 panic!("Index {index} exceeded length {}", self.len)
501 }
502 if self.is_full() {
503 panic!("Attempted to insert into full stack")
504 }
505 unsafe { self.insert_unchecked(index, data) };
506 }
507
508 /// Attempts to insert an element at position `index` in the stack,
509 /// shifting all elements after it to the right.
510 ///
511 /// If the stack is at capacity, returns the original element and an [InsertFailed] error.
512 ///
513 /// # Examples
514 ///
515 /// ```
516 /// use cl_structures::stack::Stack;
517 /// let mut v: Stack<_, 2> = Stack::new();
518 ///
519 /// assert_eq!(Ok(()), v.try_insert(0, 0));
520 /// ```
521 pub const fn try_insert(&mut self, index: usize, data: T) -> Result<(), (T, InsertFailed<N>)> {
522 if index > self.len {
523 return Err((data, InsertFailed::Bounds(index)));
524 }
525 if self.is_full() {
526 return Err((data, InsertFailed::Full));
527 }
528 // Safety: index < self.len && !self.is_full()
529 unsafe { self.insert_unchecked(index, data) };
530 Ok(())
531 }
532
533 /// # Safety:
534 /// - index must be less than self.len
535 /// - length after insertion must be <= N
536 #[inline]
537 const unsafe fn insert_unchecked(&mut self, index: usize, data: T) {
538 let base = self.as_mut_ptr();
539
540 unsafe { ptr::copy(base.add(index), base.add(index + 1), self.len - index) }
541
542 self.len += 1;
543 self.buf[index] = MaybeUninit::new(data);
544 }
545
546 /// Clears the stack
547 ///
548 /// # Examples
549 ///
550 /// ```
551 /// # use cl_structures::stack::Stack;
552 ///
553 /// let mut v = Stack::from([0, 1, 2, 3, 4]);
554 /// assert_eq!(v.as_slice(), &[0, 1, 2, 3, 4]);
555 ///
556 /// v.clear();
557 /// assert_eq!(v.as_slice(), &[]);
558 /// ```
559 pub fn clear(&mut self) {
560 // Hopefully copy elision takes care of this lmao
561 while !self.is_empty() {
562 drop(self.pop());
563 }
564 }
565
566 /// Returns the number of elements in the stack
567 /// ```
568 /// # use cl_structures::stack::*;
569 /// let v = Stack::from([0, 1, 2, 3, 4]);
570 ///
571 /// assert_eq!(5, v.len());
572 /// ```
573 pub const fn len(&self) -> usize {
574 self.len
575 }
576
577 /// Returns true if the stack is at (or over) capacity
578 ///
579 /// # Examples
580 ///
581 /// ```
582 /// # use cl_structures::stack::*;
583 /// let v = Stack::from([(); 10]);
584 ///
585 /// assert!(v.is_full());
586 /// ```
587 #[inline]
588 pub const fn is_full(&self) -> bool {
589 self.len >= N
590 }
591
592 /// Returns true if the stack contains no elements
593 ///
594 /// # Examples
595 ///
596 /// ```
597 /// # use cl_structures::stack::*;
598 /// let v: Stack<(), 10> = Stack::new();
599 ///
600 /// assert!(v.is_empty());
601 /// ```
602 #[inline]
603 pub const fn is_empty(&self) -> bool {
604 self.len == 0
605 }
606}
607
608#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
609pub enum InsertFailed<const N: usize> {
610 Bounds(usize),
611 Full,
612}
613impl<const N: usize> std::error::Error for InsertFailed<N> {}
614impl<const N: usize> std::fmt::Display for InsertFailed<N> {
615 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
616 match self {
617 InsertFailed::Bounds(idx) => write!(f, "Index {idx} exceeded length {N}"),
618 InsertFailed::Full => {
619 write!(f, "Attempt to insert into full stack (length {N})")
620 }
621 }
622 }
623}
624
625#[cfg(test)]
626mod tests {
627 use super::*;
628 #[test]
629 fn zero_sized() {
630 let v: Stack<(), { usize::MAX }> = Stack::new();
631 assert_eq!(usize::MAX, v.capacity());
632 assert_eq!(std::mem::size_of::<usize>(), std::mem::size_of_val(&v))
633 }
634 #[test]
635 fn from_usize_max_zst_array() {
636 let mut v = Stack::from([(); usize::MAX]);
637 assert_eq!(v.len(), usize::MAX);
638 v.pop();
639 assert_eq!(v.len(), usize::MAX - 1);
640 }
641
642 #[test]
643 fn new() {
644 let v: Stack<(), 255> = Stack::new();
645 assert_eq!(0, v.len());
646 assert_eq!(255, v.capacity());
647 }
648
649 #[test]
650 fn push() {
651 let mut v: Stack<_, 64> = Stack::new();
652 v.push(10);
653 }
654
655 #[test]
656 #[should_panic = "Attempted to push into full stack"]
657 fn push_overflow() {
658 let mut v = Stack::from([]);
659 v.push(10);
660 }
661
662 #[test]
663 fn pop() {
664 let mut v = Stack::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
665 assert_eq!(Some(9), v.pop());
666 assert_eq!(Some(8), v.pop());
667 assert_eq!(Some(7), v.pop());
668 assert_eq!(Some(6), v.pop());
669 assert_eq!(Some(5), v.pop());
670 assert_eq!(Some(4), v.pop());
671 assert_eq!(Some(3), v.pop());
672 assert_eq!(Some(2), v.pop());
673 assert_eq!(Some(1), v.pop());
674 assert_eq!(None, v.pop());
675 }
676
677 #[test]
678 fn resize_smaller() {
679 let v = Stack::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
680 let mut v = v.resize::<2>();
681
682 assert_eq!(2, v.capacity());
683
684 assert_eq!(Some(2), v.pop());
685 assert_eq!(Some(1), v.pop());
686 assert_eq!(None, v.pop());
687 }
688
689 #[test]
690 fn resize_bigger() {
691 let v = Stack::from([1, 2, 3, 4]);
692 let mut v: Stack<_, 10> = v.resize();
693
694 assert_eq!(Some(4), v.pop());
695 assert_eq!(Some(3), v.pop());
696 assert_eq!(Some(2), v.pop());
697 assert_eq!(Some(1), v.pop());
698 assert_eq!(None, v.pop());
699 }
700 #[test]
701 fn dangle() {
702 let mut v: Stack<_, 2> = Stack::new();
703 let a = 0;
704 let b = 1;
705 v.push(&a);
706 v.push(&b);
707 println!("{v:?}");
708 }
709 #[test]
710 fn remove() {
711 let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
712
713 assert_eq!(3, v.remove(3));
714 assert_eq!(4, v.remove(3));
715 assert_eq!(5, v.remove(3));
716 assert_eq!(Some(2), v.pop());
717 assert_eq!(Some(1), v.pop());
718 assert_eq!(Some(0), v.pop());
719 assert_eq!(None, v.pop());
720 }
721
722 #[test]
723 fn swap_remove() {
724 let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
725 assert_eq!(3, v.swap_remove(3));
726 assert_eq!(&[0, 1, 2, 5, 4], v.as_slice());
727 }
728 #[test]
729 fn swap_remove_last() {
730 let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
731 assert_eq!(5, v.swap_remove(5));
732 assert_eq!(&[0, 1, 2, 3, 4], v.as_slice())
733 }
734
735 #[test]
736 fn insert() {
737 let mut v = Stack::from([0, 1, 2, 4, 5, 0x41414141]);
738 v.pop();
739 v.insert(3, 3);
740
741 assert_eq!(&[0, 1, 2, 3, 4, 5], v.as_slice())
742 }
743
744 #[test]
745 #[should_panic = "Attempted to insert into full stack"]
746 fn insert_overflow() {
747 let mut v = Stack::from([0]);
748 v.insert(0, 1);
749 }
750
751 #[test]
752 fn drop() {
753 let v = Stack::from([
754 Box::new(0),
755 Box::new(1),
756 Box::new(2),
757 Box::new(3),
758 Box::new(4),
759 ]);
760 std::mem::drop(std::hint::black_box(v));
761 }
762
763 #[test]
764 fn drop_zst() {
765 struct Droppable;
766 impl Drop for Droppable {
767 fn drop(&mut self) {
768 use std::sync::atomic::{AtomicU32, Ordering};
769 static V: AtomicU32 = AtomicU32::new(1);
770 eprintln!("{}", V.fetch_add(1, Ordering::Relaxed));
771 }
772 }
773
774 let v = Stack::from([const { Droppable }; 10]);
775 std::mem::drop(v);
776 }
777}