astack/lib.rs
1//! `astack` offers a [`Stack`] data structure with fixed capacity capable of
2//! fast LIFO operations.
3//!
4//! The crate contains:
5//! * A [`Stack`] struct, the main object used to perform TOS operations.
6//! * A [`stack`] macro, used to conveniently construct a new [`Stack`].
7//! * A [`StackError`] used by the [`Stack`] to signal an invalid operation has occurred.
8//! * A [`StackIntoIter`] struct used to iterate over the values of a [`Stack`].
9//!
10//! `astack` may be used in both std and non-std environments, and is therefore
11//! considered platform-agnostic. The crate does not require an allocator at all!
12//!
13//! You can optionally enable the `std` feature to use some additional features,
14//! such as the `std::error::Error` implementation for [`StackError`].
15//!
16//! # Examples
17//!
18//! ## Creating an empty `Stack`
19//!
20//! ```
21//! use astack::{stack, Stack};
22//!
23//! // Through the Stack::new() method
24//! let stack = Stack::<u64, 10>::new();
25//!
26//! // Through the stack! macro
27//! let stack = stack![u64; 10];
28//! ```
29//!
30//! ## Creating a `Stack` with already some items inside
31//!
32//! ```
33//! use astack::stack;
34//!
35//! // Through the stack! macro
36//! let stack = stack! {
37//! [u64; 10] = [1, 2, 3]
38//! };
39//! ```
40//!
41//! ## Creating a `Stack` filled with items
42//!
43//! ```
44//! use astack::Stack;
45//!
46//! // A Stack filled with one single Copy item.
47//! let stack_of_44 = Stack::<u64, 10>::fill_with_copy(44);
48//!
49//! // A Stack filled with the Default implementation of u64.
50//! let stack_of_default = Stack::<u64, 10>::fill_with_default();
51//!
52//! // A Stack filled with a value based on the result of a function.
53//! let stack = Stack::<String, 10>::fill_with_fn(|i| {
54//! format!("Value n. {}", i)
55//! });
56//! ```
57//!
58//! ## Common `Stack` operations
59//!
60//! ```
61//! use astack::stack;
62//!
63//! // Create a new Stack.
64//! let mut stack = stack! {
65//! [i32; 4] = [10, 20, 30]
66//! };
67//!
68//! // Add an item as TOS. This returns Err if the stack if full.
69//! stack.push(40).unwrap();
70//!
71//! // Pop TOS. This returns None if the stack is empty.
72//! let last_value = stack.pop().unwrap();
73//!
74//! // Get a reference to TOS. This returns None if the stack is empty.
75//! assert_eq!(stack.tos(), Some(&30));
76//! ```
77
78#![warn(rust_2018_idioms, rust_2024_compatibility)]
79#![deny(
80 missing_docs,
81 missing_debug_implementations,
82 unsafe_op_in_unsafe_fn,
83 clippy::missing_safety_doc,
84 clippy::missing_errors_doc,
85 clippy::missing_inline_in_public_items,
86 clippy::missing_const_for_fn,
87 rustdoc::missing_crate_level_docs
88)]
89#![doc(html_playground_url = "https://play.rust-lang.org")]
90#![no_std]
91
92// https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-unification
93#[cfg(feature = "std")]
94extern crate std;
95
96mod iter;
97
98use core::{fmt, hash, mem, ptr};
99pub use iter::StackIntoIter;
100
101#[doc(hidden)]
102#[macro_export(local_inner_macros)]
103macro_rules! count_args {
104 ($_:expr,) => { 1 };
105 ($_:expr, $($others:expr,)+) => {
106 count_args!($_,) + count_args!($($others,)*)
107 }
108}
109
110/// A macro for conveniently creating a [`Stack`].
111///
112/// [`stack`] is used for 2 purposes:
113/// * Create an empty [`Stack`].
114/// * Create a [`Stack`] and push some items onto it.
115///
116/// The syntax is similar to one used to declare an array. If you wanted to create
117/// an array of `i32` (filled with `0`s) you'd have to go like this:
118/// ```
119/// let arr: [i32; 10] = [0; 10];
120/// ```
121///
122/// To create an empty [`Stack`], you can just declare your `T` and `N` in the macro
123/// like this:
124/// ```
125/// use astack::stack;
126/// let stack = stack![i32; 10];
127/// ```
128///
129/// or, if you want to both create and push some values at the same time, you can
130/// use the same array syntax:
131/// ```
132/// use astack::stack;
133/// let stack = stack! {
134/// [i32; 10] = [1, 2, 3]
135/// };
136/// ```
137///
138/// Note that in the last scenario [`stack`] checks at compile time if the number
139/// of values passed to the macro exceeds the capacity specified.
140///
141/// # Macro expansion
142///
143/// The code
144/// ```ignore
145/// let stack = stack![i32; 10];
146/// ```
147///
148/// expands to
149/// ```ignore
150/// let stack = Stack::<i32, 10>::new();
151/// ```
152///
153/// On the other hand, the code
154/// ```ignore
155/// let stack = stack! {
156/// [i32; 10] = [1, 2, 3]
157/// };
158/// ```
159///
160/// roughly expands to
161/// ```ignore
162/// let stack = unsafe {
163/// let mut stack = Stack::<i32, 10>::new();
164/// stack.push_unchecked(1);
165/// stack.push_unchecked(2);
166/// stack.push_unchecked(3);
167/// stack
168/// };
169/// ```
170#[macro_export(local_inner_macros)]
171macro_rules! stack {
172 ($T:ty; $N:expr) => {
173 $crate::Stack::<$T, $N>::new()
174 };
175 ([$T:ty; $N:expr] = [$($expr:expr),+ $(,)?]) => {{
176 // Compile-time error rather than runtime error
177 const _: () = core::prelude::rust_2021::assert!(
178 count_args!($($expr,)*) <= $N,
179 core::prelude::rust_2021::concat!(
180 "The number of items exceeds the capacity specified, which is ",
181 $N
182 )
183 );
184
185 let mut stack = stack![$T; $N];
186
187 // SAFETY: we have asserted before that we have enouch capacity
188 $( unsafe { stack.push_unchecked($expr) }; )*
189 stack
190 }};
191}
192
193/// The type returned by [`Stack`]'s checked operations if they fail.
194///
195/// # The `std` feature
196///
197/// If the `std` feature is enable, [`StackError`] implements `std::error::Error`.
198#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
199pub enum StackError {
200 /// Stack overflow occurs when there is not enough capacity to perform a stack
201 /// operation. Examples of that are [`push`][Stack::push] and [`extend`][Stack::extend].
202 Overflow,
203 /// Stack underflow occurs when there are not enough items to perform a stack
204 /// operation. Examples of that are [`rotate_tos`][Stack::rotate_tos] and
205 /// [`swap_tos`][Stack::swap_tos].
206 ///
207 /// From Wikipedia: For integers, the term "integer underflow" typically refers to a
208 /// special kind of integer overflow or integer wraparound condition whereby the result
209 /// of subtraction would result in a value less than the minimum allowed for a given
210 /// integer type.
211 Underflow,
212}
213
214impl fmt::Display for StackError {
215 #[inline]
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "{:?}", self)
218 }
219}
220
221/// This implementation is only available when the `std` feature is
222/// enabled.
223#[cfg(feature = "std")]
224impl std::error::Error for StackError {}
225
226/// A data structure with fixed capacity aimed at fast LIFO operations.
227///
228/// The [`Stack`] excels in working with the TOS, also known as the top of the stack.
229/// It is generic over any type `T`, and offers some implementations, such
230/// as [`Clone`], [`Debug`], [`PartialEq`] and [`Hash`] if `T` supports it as well.
231///
232/// The [`Stack`] offers three ways to manipulate data:
233/// * Checked methods, such as [`push`][Stack::push] and [`pop`][Stack::pop], which
234/// return an [`Option`] or a [`Result`]. A bit slower but *much* safer. 👍
235/// * `_panicking` methods, such as [`push_panicking`][Stack::push_panicking]
236/// and [`pop_panicking`][Stack::pop_panicking], which panic if the operation fails.
237/// * `_unchecked` methods, such as [`push_unchecked`][Stack::push_unchecked]
238/// and [`pop_unchecked`][Stack::pop_unchecked] which cause [undefined behavior]
239/// if the operation fails. The fastest choice but the unsafest! ⚠️
240///
241/// # How it works
242///
243/// A [`Stack`] is no more than a fixed size array of [`MaybeUninit`] and an [`usize`]
244/// that keeps track of the items count and is in charge of bound checking.
245/// The usage of [`MaybeUninit`] enhances the performance of the data structure,
246/// as it only allocates when needed. The [`Stack`] makes usage of [`unsafe`] code
247/// internally to handle data through raw pointers, and further increase the
248/// speed of read/write/swap operations.
249///
250/// # Safety
251///
252/// Users are recommended to rely on the checked methods or the `_panicking` ones,
253/// even though the second category should be used for testing and teaching purposes,
254/// as it does not allow for proper error handling by panicking on error.
255/// If deemed necessary, `_unchecked` (but faster) versions of the safe methods
256/// are available. These ones skip the safety checks, but will result in
257/// *[undefined behavior]* if the user does not respect the [safety contract].
258///
259/// If the user is certain that the safety contract is guaranteed to be respected,
260/// the `_unchecked` versions are available for use. However, as mentioned in the
261/// beginning of this paragraph, most of the time users will be happy enough to
262/// rely on the safe counterparts and trade off a bit of performance to avoid UB.
263///
264/// # Examples
265///
266/// ## Creating an empty `Stack`
267///
268/// ```
269/// use astack::{stack, Stack};
270///
271/// // Through the Stack::new() method
272/// let stack = Stack::<u64, 10>::new();
273///
274/// // Through the stack! macro
275/// let stack = stack![u64; 10];
276/// ```
277///
278/// ## Creating a `Stack` with already some items inside
279///
280/// ```
281/// use astack::stack;
282///
283/// // Through the stack! macro
284/// let stack = stack! {
285/// [u64; 10] = [1, 2, 3]
286/// };
287/// ```
288///
289/// ## Creating a `Stack` filled with items
290///
291/// ```
292/// use astack::Stack;
293///
294/// // A Stack filled with one single Copy item.
295/// let stack_of_44 = Stack::<u64, 10>::fill_with_copy(44);
296///
297/// // A Stack filled with the Default implementation of `T`.
298/// let stack_of_default = Stack::<u64, 10>::fill_with_default();
299///
300/// // A Stack filled with a value based on the result of a function.
301/// let stack = Stack::<String, 10>::fill_with_fn(|i| {
302/// format!("Value n. {}", i)
303/// });
304/// ```
305///
306/// ## List of all checked `Stack` operations
307/// | Name | Description |
308/// |---|---|
309/// | [`push`][Stack::push] | Push an item |
310/// | [`extend`][Stack::extend] | Push many items |
311/// | [`extend_array`][Stack::extend_array] | Push many items from an array |
312/// | [`pop`][Stack::pop] | Pop and return an item |
313/// | [`cut`][Stack::cut] | Pop and return many items |
314/// | [`tos`][Stack::tos] | Get a reference to TOS |
315/// | [`tos_mut`][Stack::tos_mut] | Get a mutable reference to TOS |
316/// | [`truncate`][Stack::truncate] | Pop and discard many items |
317/// | [`swap_tos`][Stack::swap_tos] | Replace TOS with an item |
318/// | [`rotate_tos`][Stack::rotate_tos] | Swap TOS with TOS - 1: |
319///
320/// [`MaybeUninit`]: core::mem::MaybeUninit
321/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
322/// [safety contract]: https://doc.rust-lang.org/std/keyword.unsafe.html
323/// [`Debug`]: core::fmt::Debug
324/// [`Hash`]: core::hash::Hash
325/// [`unsafe`]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
326pub struct Stack<T, const N: usize> {
327 items: [mem::MaybeUninit<T>; N],
328 len: usize,
329}
330
331impl<T, const N: usize> Stack<T, N> {
332 /// Returns a new empty [`Stack`] with its items uninitialized.
333 ///
334 /// * If you want to get a [`Stack`] filled with [`Copy`] items, see
335 /// [`fill_with_copy`][Stack::fill_with_copy].
336 /// * If you want to get a [`Stack`] filled with [`Default`] items, see
337 /// [`fill_with_default`][Stack::fill_with_default].
338 /// * If you want to get a [`Stack`] filled with the value returned by a function,
339 /// see [`fill_with_fn`][Stack::fill_with_fn].
340 ///
341 /// # Examples
342 ///
343 /// ```
344 /// use astack::{Stack, stack};
345 /// // Create an empty Stack which can hold up to 10 String.
346 /// let stack1 = Stack::<String, 10>::new();
347 ///
348 /// // You can achieve the same result with the stack! macro.
349 /// let same_as_stack1 = stack![String; 10];
350 ///
351 /// // Both stacks do not have initialized items.
352 /// assert!(stack1.is_empty() && same_as_stack1.is_empty());
353 /// ```
354 #[inline]
355 pub const fn new() -> Self {
356 Self {
357 // SAFETY: The `assume_init` is safe because the type we are claiming
358 // to have initialized here is a bunch of `MaybeUninit`s, which do not
359 // require initialization.
360 // https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
361 items: unsafe { mem::MaybeUninit::uninit().assume_init() },
362 len: 0,
363 }
364 }
365
366 /// Returns a [`Stack`] filled with `item`. Only works if `item` implements [`Copy`].
367 /// This is optimized for types which implement [`Copy`].
368 ///
369 /// * If you want to get a [`Stack`] filled with [`Default`] items, see
370 /// [`fill_with_default`][Stack::fill_with_default].
371 /// * If you want to get a [`Stack`] filled with the value returned by a function,
372 /// see [`fill_with_fn`][Stack::fill_with_fn].
373 ///
374 /// # Examples
375 /// ```
376 /// use astack::Stack;
377 ///
378 /// // A stack full of 42.
379 /// let stack_of_42 = Stack::<u8, 50>::fill_with_copy(42);
380 /// assert!(stack_of_42.is_full());
381 /// assert_eq!(stack_of_42.tos(), Some(&42));
382 ///
383 /// ```
384 ///
385 /// [this link]: https://doc.rust-lang.org/std/primitive.array.html
386 #[inline]
387 pub const fn fill_with_copy(item: T) -> Self
388 where
389 T: Copy,
390 {
391 Self {
392 items: [mem::MaybeUninit::new(item); N],
393 len: N,
394 }
395 }
396
397 /// Returns a [`Stack`] filled with the item returned by `f`. This is useful
398 /// to create a [`Stack`] out of non-[`Copy`] and non-[`Default`] items.
399 /// The `f` takes as input a [`usize`] which is the i-th index
400 ///
401 /// * If you want to get a [`Stack`] filled with [`Copy`] items, see
402 /// [`fill_with_copy`][Stack::fill_with_copy].
403 /// * If you want to get a [`Stack`] filled with [`Default`] items, see
404 /// [`fill_with_default`][Stack::fill_with_default].
405 ///
406 /// # Examples
407 ///
408 /// ```
409 /// use astack::Stack;
410 ///
411 /// fn long_computation(i: usize) -> String {
412 /// // Perform a long and heavy computation...
413 /// format!("Item n. {}", i)
414 /// }
415 ///
416 /// let stack = Stack::<String, 32>::fill_with_fn(long_computation);
417 /// assert!(stack.is_full());
418 /// assert_eq!(stack.tos(), Some(&String::from("Item n. 31")));
419 /// ```
420 #[inline]
421 pub fn fill_with_fn<F>(mut f: F) -> Self
422 where
423 F: FnMut(usize) -> T,
424 {
425 Self {
426 items: core::array::from_fn(|i| mem::MaybeUninit::new(f(i))),
427 len: N,
428 }
429 }
430
431 /// Returns a [`Stack`] filled with the default value for `T`.
432 ///
433 /// * If you want to get a [`Stack`] filled with [`Copy`] items, see
434 /// [`fill_with_copy`][Stack::fill_with_copy].
435 /// * If you want to get a [`Stack`] filled with the value returned by a function,
436 /// see [`fill_with_fn`][Stack::fill_with_fn].
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use astack::Stack;
442 ///
443 /// // A Stack filled with empty Strings
444 /// let stack = Stack::<String, 4>::fill_with_default();
445 /// assert!(stack.is_full());
446 /// assert_eq!(stack.tos(), Some(&String::default()));
447 /// ```
448 #[inline]
449 pub fn fill_with_default() -> Self
450 where
451 T: Default,
452 {
453 Self::fill_with_fn(|_| T::default())
454 }
455
456 /// Builds a [`Stack`] from an array of [`MaybeUninit`] and a `len`,
457 /// representing the count of initialized items.
458 ///
459 /// # Safety
460 ///
461 /// Building a [`Stack`] using [`from_raw_parts`][Stack::from_raw_parts] is
462 /// *[undefined behavior]* if one of the following occurs:
463 /// * `len` is greater than the maximum number of items the stack is allowed to hold.
464 ///
465 /// * `items[..len]` is composed of uninitialized [`MaybeUninit`].
466 ///
467 /// # Leaking
468 ///
469 /// Building a [`Stack`] using [`from_raw_parts`][Stack::from_raw_parts]
470 /// will cause a memory leak if both conditions are met:
471 ///
472 /// * `items[len..N]` is composed of one or more already initialized [`MaybeUninit`].
473 ///
474 /// * `T` does not implement [`Copy`].
475 ///
476 /// # Examples
477 ///
478 /// ```
479 /// use std::mem;
480 /// use astack::{Stack, stack};
481 ///
482 /// // Create a stack from raw parts.
483 /// // [3, 2, 1, (uninit)]
484 /// let items = [
485 /// mem::MaybeUninit::new(3),
486 /// mem::MaybeUninit::new(2),
487 /// mem::MaybeUninit::new(1),
488 /// mem::MaybeUninit::uninit(),
489 /// ];
490 /// let len = 3;
491 ///
492 /// // Safety: the items have been initialized in the correct way.
493 /// // Safety: len correctly represents the count of initialized items.
494 ///
495 /// let stack = unsafe { Stack::from_raw_parts(items, len) };
496 /// assert_eq!(stack.len(), 3);
497 /// assert_eq!(stack.tos(), Some(&1));
498 /// assert_eq!(stack, stack! {
499 /// [i32; 4] = [3, 2, 1]
500 /// });
501 /// ```
502 ///
503 /// [`MaybeUninit`]: core::mem::MaybeUninit
504 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
505 #[inline]
506 pub const unsafe fn from_raw_parts(items: [mem::MaybeUninit<T>; N], len: usize) -> Self {
507 debug_assert!(len <= N);
508 Self { items, len }
509 }
510
511 /// Returns `true` if the stack does not have initialized items, and is therefore
512 /// considered empty.
513 ///
514 /// # Examples
515 ///
516 /// ```
517 /// use astack::stack;
518 ///
519 /// // Create an empty stack
520 /// let mut stack = stack![i32; 16];
521 /// assert!(stack.is_empty());
522 ///
523 /// // Add items
524 /// stack.push_panicking(42);
525 /// stack.push_panicking(69);
526 ///
527 /// // Not the stack is not empty anymore!
528 /// assert!(!stack.is_empty());
529 /// ```
530 #[inline]
531 pub const fn is_empty(&self) -> bool {
532 self.len == 0
533 }
534
535 /// Returns `true` if the stack contains only initialized items, and is therefore
536 /// considered full.
537 ///
538 /// # Examples
539 ///
540 /// ```
541 /// use astack::stack;
542 ///
543 /// // Create a stack full of custom items.
544 /// let mut stack = stack! {
545 /// [i64; 4] = [567, 212, 890, 90]
546 /// };
547 /// assert!(stack.is_full());
548 ///
549 /// // Remove an item.
550 /// stack.pop_panicking();
551 ///
552 /// // Not the stack is not full anymore, even if there are
553 /// // still three items inside!
554 /// assert!(!stack.is_full());
555 /// ```
556 #[inline]
557 pub const fn is_full(&self) -> bool {
558 self.len >= N
559 }
560
561 /// Returns the number of initialized items in the stack, also referred to
562 /// as its 'len'.
563 ///
564 /// # Examples
565 ///
566 /// ```
567 /// use astack::stack;
568 ///
569 /// let stack = stack! {
570 /// [bool; 10] = [false, true, false]
571 /// };
572 /// assert_eq!(stack.len(), 3);
573 /// ```
574 #[inline]
575 pub const fn len(&self) -> usize {
576 self.len
577 }
578
579 /// Returns the capacity of the stack. Remember that a [`Stack`] has a fixed
580 /// capacity!
581 ///
582 /// This does not return the *remaining* capacity, but rather the total capacity
583 /// that was given as input when the [`Stack`] was created, i.e., the number of
584 /// items that the stack is able to hold.
585 ///
586 /// # Examples
587 ///
588 /// ```
589 /// use astack::stack;
590 ///
591 /// let mut stack = stack![i32; 10];
592 /// assert_eq!(stack.capacity(), 10);
593 ///
594 /// // Even if we push some items, the capacity remains the same.
595 /// stack.push_panicking(50);
596 /// stack.push_panicking(150);
597 ///
598 /// assert_eq!(stack.len(), 2);
599 /// assert_eq!(stack.capacity(), 10);
600 /// ```
601 #[inline]
602 pub const fn capacity(&self) -> usize {
603 N
604 }
605
606 /// Returns the number of items the stack can push before becoming full.
607 ///
608 /// # Examples
609 ///
610 /// ```
611 /// use astack::stack;
612 ///
613 /// let mut stack = stack![i32; 5];
614 /// // The stack is empty now.
615 /// assert_eq!(stack.capacity_remaining(), 5);
616 ///
617 /// // Add some items.
618 /// stack.extend_array_panicking([7, 8, 9]);
619 ///
620 /// assert_eq!(stack.capacity_remaining(), 2);
621 /// ```
622 #[inline]
623 pub const fn capacity_remaining(&self) -> usize {
624 N - self.len
625 }
626
627 /// Returns a reference to the top of the stack or [`None`] if it is empty.
628 /// This does not remove TOS from the stack.
629 ///
630 /// # Examples
631 ///
632 /// ```
633 /// use astack::stack;
634 ///
635 /// let mut stack = stack! {
636 /// [&str; 3] = ["my", "body!"]
637 /// };
638 ///
639 /// // The top of the stack is the last inserted one!
640 /// let tos = stack.tos();
641 /// assert_eq!(tos, Some(&"body!"));
642 ///
643 /// // Remove all items
644 /// stack.clear();
645 ///
646 /// assert_eq!(stack.tos(), None);
647 /// ```
648 #[inline]
649 pub const fn tos(&self) -> Option<&T> {
650 if self.is_empty() {
651 None
652 } else {
653 Some(unsafe { self.tos_unchecked() })
654 }
655 }
656
657 /// Returns a reference to the top of the stack. This does not remove TOS from
658 /// the stack.
659 /// # Panics
660 ///
661 /// Panics if the stack is empty.
662 ///
663 /// # Examples
664 ///
665 /// ```
666 /// use astack::stack;
667 ///
668 /// // An empty stack has no TOS!
669 /// let mut stack = stack![i32; 100];
670 /// stack.push_panicking(80);
671 ///
672 /// // This example would panic if there was no TOS.
673 /// assert_eq!(stack.tos_panicking(), &80);
674 /// ```
675 #[inline]
676 pub const fn tos_panicking(&self) -> &T {
677 assert!(
678 !self.is_empty(),
679 "Called Stack::tos_panicking on an empty stack"
680 );
681 unsafe { self.tos_unchecked() }
682 }
683
684 /// Returns a reference to the top of the stack without checking whether
685 /// the latter is empty or not. For a safe alternative see [`tos`][Stack::tos]
686 /// or [`tos_panicking`][Stack::tos_panicking]. This does not remove TOS from
687 /// the stack.
688 ///
689 /// # Safety
690 ///
691 /// Calling this method on an empty stack is *[undefined behavior]*
692 /// even if the resulting reference is not used.
693 ///
694 /// # Examples
695 ///
696 /// ```
697 /// use astack::stack;
698 ///
699 /// let mut stack = stack! {
700 /// [&str; 3] = ["my", "body!"]
701 /// };
702 ///
703 /// // We know that the tos exists, so we use the unchecked version.
704 /// let tos = unsafe { stack.tos_unchecked() };
705 /// assert_eq!(tos, &"body!");
706 ///
707 /// // Remove all items
708 /// stack.clear();
709 ///
710 /// // The following line will cause undefined behavior
711 /// // if commented out!
712 /// // let tos = unsafe { stack.tos_unchecked() };
713 /// ```
714 ///
715 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
716 #[inline]
717 pub const unsafe fn tos_unchecked(&self) -> &T {
718 debug_assert!(!self.is_empty());
719
720 // SAFETY: the caller must uphold the safety requirements
721 // (self.len must be > 0)
722 //
723 // The following is the same as SliceIndex::get_unchecked with usize
724 // By not using the trait method, we can make this function const
725 unsafe { (*self.items.as_ptr().add(self.len - 1)).assume_init_ref() }
726 }
727
728 /// Returns a mutable reference to the top of the stack or [`None`]
729 /// if it is empty. This does not remove TOS from the stack.
730 ///
731 /// # Examples
732 ///
733 /// ```
734 /// use astack::stack;
735 ///
736 /// // A stack with one item: the number 0.
737 /// let mut stack = stack! {
738 /// [i32; 8] = [0]
739 /// };
740 /// assert_eq!(stack.tos(), Some(&0));
741 ///
742 /// // Increment tos by 10
743 /// if let Some(tos) = stack.tos_mut() {
744 /// *tos += 10;
745 /// }
746 ///
747 /// assert_eq!(stack.tos(), Some(&10));
748 /// ```
749 #[inline]
750 pub fn tos_mut(&mut self) -> Option<&mut T> {
751 if self.is_empty() {
752 None
753 } else {
754 Some(unsafe { self.tos_mut_unchecked() })
755 }
756 }
757
758 /// Returns a mutable reference to the top of the stack. This does not remove TOS from
759 /// the stack.
760 ///
761 /// # Panics
762 ///
763 /// Panics if the stack is empty.
764 ///
765 /// # Examples
766 ///
767 /// ```
768 /// use astack::stack;
769 ///
770 /// // A stack with one item: the number 0.
771 /// let mut stack = stack! {
772 /// [i32; 8] = [0]
773 /// };
774 ///
775 /// // The following like would cause a panic if the stack was empty!
776 /// let mut tos = stack.tos_mut_panicking();
777 /// assert_eq!(tos, &mut 0);
778 ///
779 /// // Increment tos by 10
780 /// *tos += 10;
781 ///
782 /// assert_eq!(stack.tos_mut_panicking(), &mut 10);
783 /// ```
784 #[inline]
785 pub fn tos_mut_panicking(&mut self) -> &mut T {
786 assert!(
787 !self.is_empty(),
788 "Called Stack::tos_mut_panicking on an empty stack"
789 );
790 unsafe { self.tos_mut_unchecked() }
791 }
792
793 /// Returns a mutable reference to the top of the stack without checking
794 /// whether the latter is empty or not. For a safe alternative see
795 /// [`tos_mut`][Stack::tos_mut] or [`tos_mut_panicking`][Stack::tos_mut_panicking].
796 /// This does not remove TOS from the stack.
797 ///
798 /// # Safety
799 ///
800 /// Calling this method on an empty stack is *[undefined behavior]*
801 /// even if the resulting reference is not used.
802 ///
803 /// # Examples
804 ///
805 /// ```
806 /// use astack::stack;
807 ///
808 /// let mut stack = stack! {
809 /// [char; 10] = ['a', 'b']
810 /// };
811 ///
812 /// // We know that there must be a tos
813 /// // Increment tos ascii value by one
814 /// let tos = unsafe { stack.tos_mut_unchecked() };
815 /// *tos = (*tos as u8 + 1) as char;
816 ///
817 /// assert_eq!(stack.tos(), Some(&'c'));
818 /// ```
819 ///
820 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
821 #[inline]
822 pub unsafe fn tos_mut_unchecked(&mut self) -> &mut T {
823 debug_assert!(!self.is_empty());
824
825 // SAFETY: the caller must uphold the safety requirements
826 // (self.len must be > 0)
827 //
828 // The following is the same as SliceIndex::get_unchecked with usize
829 // By not using the trait method, we can make this function const (not yet!)
830 unsafe { (*self.items.as_mut_ptr().add(self.len - 1)).assume_init_mut() }
831 }
832
833 /// Pushes an item at the top of the stack.
834 ///
835 /// # Errors
836 ///
837 /// Returns [`StackError`] if the stack is full.
838 ///
839 /// # Examples
840 ///
841 /// ```
842 /// use astack::{Stack, StackError};
843 ///
844 /// // Create a full stack.
845 /// let mut stack = Stack::<i16, 20>::fill_with_copy(100);
846 ///
847 /// // Try to push `my_lucky_num`.
848 /// let my_lucky_num = 16;
849 /// assert_eq!(stack.push(my_lucky_num), Err(StackError::Overflow));
850 ///
851 /// // Make some space for `my_lucky_num`.
852 /// stack.clear();
853 ///
854 /// assert_eq!(stack.push(my_lucky_num), Ok(()));
855 /// ```
856 #[inline]
857 pub fn push(&mut self, item: T) -> Result<(), StackError> {
858 if self.is_full() {
859 Err(StackError::Overflow)
860 } else {
861 unsafe { self.push_unchecked(item) };
862 Ok(())
863 }
864 }
865
866 /// Pushes an item at the top of the stack
867 ///
868 /// # Panics
869 ///
870 /// Panics if the stack is full.
871 ///
872 /// # Examples
873 ///
874 /// ```
875 /// use astack::{Stack, StackError};
876 ///
877 /// // Create a full stack.
878 /// let mut stack = Stack::<i16, 20>::fill_with_copy(100);
879 ///
880 /// // Try to push `my_lucky_num`.
881 /// let my_lucky_num = 16;
882 ///
883 /// // The following line, if commented out, would cause a panic!
884 /// // assert_eq!(stack.push(my_lucky_num), Err(StackError::Overflow));
885 ///
886 /// // Make some space for `my_lucky_num`.
887 /// stack.clear();
888 ///
889 /// // Now it is safe to push_panicking.
890 /// stack.push_panicking(my_lucky_num);
891 /// assert_eq!(stack.tos(), Some(&16));
892 /// ```
893 #[inline]
894 pub fn push_panicking(&mut self, item: T) {
895 assert!(
896 !self.is_full(),
897 "Called Stack::push_panicking but the stack is full"
898 );
899 unsafe { self.push_unchecked(item) };
900 }
901
902 /// Pushes an item at the top of the stack, without checking whether the latter
903 /// is full or not. For a safe alternative, see [`push`][Stack::push] or
904 /// [`push_panicking`][Stack::push_panicking].
905 ///
906 /// # Safety
907 ///
908 /// Calling this method if the stack is full is *[undefined behavior]*.
909 ///
910 /// # Examples
911 /// ```
912 /// use astack::stack;
913 ///
914 /// let mut my_stack1 = stack![i32; 10];
915 ///
916 /// // Fill the stack manually.
917 /// for i in 0..10 {
918 /// unsafe {
919 /// my_stack1.push_unchecked(i);
920 /// }
921 /// }
922 ///
923 /// // The following line if commented out, would result in undefined behavior!
924 /// // unsafe { my_stack1.push_unchecked(11); }
925 /// ```
926 ///
927 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
928 #[inline]
929 pub unsafe fn push_unchecked(&mut self, item: T) {
930 debug_assert!(!self.is_full());
931
932 // SAFETY: the caller must uphold the safety requirements (self.len < N).
933 //
934 // This is similar to Vec::push
935 unsafe {
936 let end = self.items.as_mut_ptr().add(self.len);
937 ptr::write(end, mem::MaybeUninit::new(item));
938 }
939 self.len += 1;
940 }
941
942 /// Removes the top of the stack and returns it, or [`None`] if the stack
943 /// is empty.
944 ///
945 /// # Examples
946 ///
947 /// ```
948 /// use astack::stack;
949 ///
950 /// let mut stack = stack!{
951 /// [i32; 16] = [10, 20, 30]
952 /// };
953 ///
954 /// assert_eq!(stack.pop(), Some(30));
955 /// assert_eq!(stack.pop(), Some(20));
956 /// assert_eq!(stack.pop(), Some(10));
957 /// assert_eq!(stack.pop(), None);
958 /// ```
959 #[inline]
960 pub fn pop(&mut self) -> Option<T> {
961 if self.is_empty() {
962 None
963 } else {
964 Some(unsafe { self.pop_unchecked() })
965 }
966 }
967
968 /// Removes the top of the stack and returns it
969 ///
970 /// # Panics
971 ///
972 /// Panics if the stack is empty.
973 ///
974 /// # Examples
975 ///
976 /// ```
977 /// use astack::stack;
978 ///
979 /// let mut stack = stack!{
980 /// [i32; 16] = [10, 20, 30]
981 /// };
982 ///
983 /// // Cannot pop_unchecked more than 3 times, otherwise a panic occurs!
984 /// assert_eq!(stack.pop_panicking(), 30);
985 /// assert_eq!(stack.pop_panicking(), 20);
986 /// assert_eq!(stack.pop_panicking(), 10);
987 /// ```
988 #[inline]
989 pub fn pop_panicking(&mut self) -> T {
990 assert!(
991 !self.is_empty(),
992 "Called Stack::pop_panicking but the stack is empty"
993 );
994 unsafe { self.pop_unchecked() }
995 }
996
997 /// Removes the top of the stack and returns it, without checking whether
998 /// the latter is empty or not. For a safe alternative, see [`pop`][Stack::pop]
999 /// or [`pop_panicking`][Stack::pop_panicking].
1000 ///
1001 /// # Safety
1002 ///
1003 /// Calling this method if the stack is empty is *[undefined behavior]*.
1004 ///
1005 /// # Examples
1006 ///
1007 /// ```
1008 /// use astack::stack;
1009 ///
1010 /// let mut stack = stack! {
1011 /// [char; 4] = ['a', 'b']
1012 /// };
1013 ///
1014 /// // We know there are exactly 2 items at this point, so it is safe to use
1015 /// // the unchecked version.
1016 /// unsafe {
1017 /// assert_eq!(stack.pop_unchecked(), 'b');
1018 /// assert_eq!(stack.pop_unchecked(), 'a');
1019 /// }
1020 ///
1021 /// // If commented out, the following line results in undefined behavior!
1022 /// // unsafe { stack.pop_unchecked(); };
1023 /// ```
1024 ///
1025 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1026 #[inline]
1027 pub unsafe fn pop_unchecked(&mut self) -> T {
1028 debug_assert!(!self.is_empty());
1029
1030 // SAFETY: the caller must uphold the safety requirements
1031 // (self.len > 0)
1032 // (self.items.as_ptr().add(self.len) must be in an initialized state)
1033 //
1034 // This is similar to Vec::pop
1035 self.len -= 1;
1036 unsafe { ptr::read(self.items.as_ptr().add(self.len)).assume_init() }
1037 }
1038
1039 /// Pushes items of an array of length `M` on the stack. This is optimized
1040 /// for arrays, and should be preferred before [`extend`][Stack::extend]
1041 /// if you have an array of elements.
1042 ///
1043 /// # Errors
1044 ///
1045 /// Returns [`StackError`] if the stack cannot hold `M` more items
1046 /// (`stack.len() + M > stack.capacity()`).
1047 ///
1048 /// # Examples
1049 ///
1050 /// ```
1051 /// use astack::{stack, StackError};
1052 ///
1053 /// let mut stack = stack! {
1054 /// [i32; 5] = [1, 2, 3]
1055 /// };
1056 ///
1057 /// // Extend the stack
1058 /// stack.extend_array([4, 5]).unwrap();
1059 /// assert_eq!(stack.tos(), Some(&5));
1060 /// assert_eq!(stack, [1, 2, 3, 4, 5]);
1061 ///
1062 /// // The stack is full: cannot push more items!
1063 /// assert_eq!(stack.extend_array([6, 7, 8]), Err(StackError::Overflow));
1064 /// ```
1065 #[inline]
1066 pub fn extend_array<const M: usize>(&mut self, arr: [T; M]) -> Result<(), StackError> {
1067 if self.len + M > N {
1068 Err(StackError::Overflow)
1069 } else {
1070 unsafe { self.extend_array_unchecked(arr) };
1071 Ok(())
1072 }
1073 }
1074
1075 /// Pushes items of an array of length `M` on the stack. This is optimized
1076 /// for arrays, and should be preferred before [`extend_panicking`][Stack::extend_panicking]
1077 /// if you have an array of elements.
1078 ///
1079 /// # Panics
1080 ///
1081 /// Panics if the stack cannot hold `M` more items
1082 /// (`stack.len() + M > stack.capacity()`).
1083 ///
1084 /// # Examples
1085 ///
1086 /// ```should_panic
1087 /// use astack::stack;
1088 ///
1089 /// let mut characters = stack![char; 4];
1090 ///
1091 /// // Extend operations
1092 /// characters.extend_array_panicking(['x', 'y']);
1093 /// characters.extend_array_panicking(['z', '_']);
1094 /// assert_eq!(characters, ['x', 'y', 'z', '_']);
1095 ///
1096 /// // The following line makes the program crash!
1097 /// characters.extend_array_panicking(['a', 'b']);
1098 /// ```
1099 #[inline]
1100 pub fn extend_array_panicking<const M: usize>(&mut self, arr: [T; M]) {
1101 assert!(
1102 self.len + M <= N,
1103 "Called Stack::push_array_panicking but self.len + M > N"
1104 );
1105 unsafe { self.extend_array_unchecked(arr) };
1106 }
1107
1108 /// Pushes items of an array of length `M` on the stack. This is optimized
1109 /// for arrays, and should be preferred before [`extend_panicking`][Stack::extend_panicking]
1110 /// if you have an array of elements.
1111 ///
1112 /// # Safety
1113 ///
1114 /// Calling this method if `stack.len() + M > stack.capacity()` is
1115 /// *[undefined behavior]*.
1116 ///
1117 /// # Examples
1118 ///
1119 /// ```
1120 /// use astack::stack;
1121 ///
1122 /// let mut characters = stack![char; 4];
1123 ///
1124 /// // SAFETY: we know that at this point the stack can hold exactly 4 characters
1125 /// // and therefore it is safe to pass an array of 4 chars.
1126 /// unsafe {
1127 /// characters.extend_array_unchecked(['7', '8', '9', '0']);
1128 /// }
1129 /// assert_eq!(characters, ['7', '8', '9', '0']);
1130 ///
1131 /// // The following line, if uncommented, causes undefined behavior.
1132 /// // characters.extend_array_unchecked(['a', 'b']);
1133 /// ```
1134 ///
1135 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1136 #[inline]
1137 pub unsafe fn extend_array_unchecked<const M: usize>(&mut self, arr: [T; M]) {
1138 debug_assert!(self.len + M <= N);
1139 let mut arr = arr.map(|item| mem::MaybeUninit::new(item));
1140
1141 // SAFETY: this is similar to slice::swap_with_slice. The slices cannot
1142 // overlap because mutable references are exclusive.
1143 unsafe {
1144 ptr::swap_nonoverlapping(
1145 self.items[self.len..(self.len + M)].as_mut_ptr(),
1146 arr[..].as_mut_ptr(),
1147 M,
1148 );
1149 }
1150 self.len += M;
1151 }
1152
1153 /// Moves items of an [`IntoIterator`] onto the stack. This is the equivalent of calling
1154 /// [`push`][Stack::push] for each item of the [`IntoIterator`]. If you want to push
1155 /// items of an array, see [`extend_array`][Stack::extend_array].
1156 ///
1157 /// # Errors
1158 ///
1159 /// Returns [`StackError`] if the stack runs out of capacity while inserting
1160 /// the items.
1161 ///
1162 /// # Examples
1163 ///
1164 /// ```
1165 /// use astack::{stack, StackError};
1166 ///
1167 /// let mut stack = stack![u8; 7];
1168 ///
1169 /// // This works!
1170 /// stack.extend(0..2).unwrap();
1171 /// assert_eq!(stack, [0, 1]);
1172 ///
1173 /// // All types that support IntoIterator can be used with `extend`.
1174 /// stack.extend("aa".chars().map(|ch| ch as _)).unwrap();
1175 /// assert_eq!(stack, [0, 1, 97, 97]);
1176 ///
1177 /// // NOT RECOMMENDED: use `extend_array` for that.
1178 /// stack.extend([4, 5, 6]).unwrap();
1179 /// assert_eq!(stack.tos(), Some(&6));
1180 ///
1181 /// // The stack is at full capacity!
1182 /// assert_eq!(stack.extend(1..), Err(StackError::Overflow));
1183 /// ```
1184 #[inline]
1185 pub fn extend<I>(&mut self, items: I) -> Result<(), StackError>
1186 where
1187 I: IntoIterator<Item = T>,
1188 {
1189 items.into_iter().try_for_each(|item| self.push(item))
1190 }
1191
1192 /// Moves items of an [`IntoIterator`] onto the stack. This is the equivalent of calling
1193 /// [`push_panicking`][Stack::push_panicking] for each item of the [`IntoIterator`].
1194 /// If you want to push items of an array, see
1195 /// [`extend_array_panicking`][Stack::extend_array_panicking].
1196 ///
1197 /// # Panics
1198 ///
1199 /// Panics if the stack runs out of capacity while inserting the items.
1200 ///
1201 /// # Examples
1202 ///
1203 /// ```should_panic
1204 /// use astack::stack;
1205 ///
1206 /// let mut stack = stack![u8; 7];
1207 ///
1208 /// // This works!
1209 /// stack.extend_panicking(0..5);
1210 /// assert_eq!(stack, [0, 1, 2, 3, 4]);
1211 ///
1212 /// // All types that support IntoIterator can be used with `extend_panicking`.
1213 /// stack.extend_panicking("ee".chars().map(|ch| ch as _));
1214 /// assert_eq!(stack, [0, 1, 2, 3, 4, 101, 101]);
1215 /// assert!(stack.is_full());
1216 ///
1217 /// // The stack is at full capacity! The program panics at the line below.
1218 /// stack.extend_panicking(1..);
1219 /// ```
1220 #[inline]
1221 pub fn extend_panicking<I>(&mut self, items: I)
1222 where
1223 I: IntoIterator<Item = T>,
1224 {
1225 items.into_iter().for_each(|item| self.push_panicking(item));
1226 }
1227
1228 /// Moves items of an [`IntoIterator`] onto the stack without checking for overflow.
1229 /// This is the equivalent of calling [`push_unchecked`][Stack::push_unchecked]
1230 /// for each item of the [`IntoIterator`]. If you want to push items of an array, see
1231 /// [`extend_array_unchecked`][Stack::extend_array_unchecked].
1232 ///
1233 /// # Safety
1234 ///
1235 /// If the [`IntoIterator`] overflows the capacity of the stack, *[undefined behavior]*
1236 /// occurs.
1237 ///
1238 /// # Examples
1239 ///
1240 /// ```
1241 /// use astack::stack;
1242 ///
1243 /// let mut stack = stack![char; 4];
1244 ///
1245 /// // SAFETY: we know there is enough capacity to do this.
1246 /// unsafe {
1247 /// stack.extend_unchecked("lmao".chars());
1248 /// }
1249 /// assert_eq!(stack, ['l', 'm', 'a', 'o']);
1250 ///
1251 /// // The following line, if commented out, causes undefined behavior!
1252 /// // unsafe { stack.extend_unchecked("ub".chars()) };
1253 /// ```
1254 ///
1255 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1256 #[inline]
1257 pub unsafe fn extend_unchecked<I>(&mut self, items: I)
1258 where
1259 I: IntoIterator<Item = T>,
1260 {
1261 // SAFETY: the safety contract of Stack::push_unchecked applies.
1262 items
1263 .into_iter()
1264 .for_each(|item| unsafe { self.push_unchecked(item) });
1265 }
1266
1267 /// Pops `M` items from the stack and returns them as an array (no dynamic
1268 /// allocation is involved). The order of the items is preserved: the stack
1269 /// is literally 'cut'.
1270 ///
1271 /// # Errors
1272 ///
1273 /// Returns [`StackError`] if `M > stack.len`, i.e., the requested number of
1274 /// items exceeds the number of items available. No item is removed if the
1275 /// operation is invalid.
1276 ///
1277 /// # Examples
1278 ///
1279 /// ```
1280 /// use astack::{stack, StackError};
1281 ///
1282 /// let mut greetings = stack! {
1283 /// [&str; 5] = ["hello", "ciao", "hola", "salut"]
1284 /// };
1285 ///
1286 /// let arr = greetings.cut::<2>();
1287 ///
1288 /// // The order of the items is preserved.
1289 /// assert_eq!(arr, Ok(["hola", "salut"]));
1290 /// assert_eq!(greetings, ["hello", "ciao"]);
1291 /// assert_eq!(greetings.tos(), Some(&"ciao"));
1292 ///
1293 /// // Not enough items!
1294 /// let invalid = greetings.cut::<3>();
1295 /// assert_eq!(invalid, Err(StackError::Underflow));
1296 ///
1297 /// // No item is removed if the operation is invalid.
1298 /// assert_eq!(greetings, ["hello", "ciao"])
1299 /// ```
1300 #[inline]
1301 #[must_use = "If you want to discard the result, see `Stack::truncate`"]
1302 pub fn cut<const M: usize>(&mut self) -> Result<[T; M], StackError> {
1303 if M > self.len {
1304 Err(StackError::Underflow)
1305 } else {
1306 Ok(unsafe { self.cut_unchecked() })
1307 }
1308 }
1309
1310 /// Pops `M` items from the stack and returns them as an array (no dynamic
1311 /// allocation is involved). The order of the items is preserved: the stack
1312 /// is literally 'cut'.
1313 ///
1314 /// # Panics
1315 ///
1316 /// Panics if `M > stack.len`, i.e., the requested number of
1317 /// items exceeds the number of items available.
1318 ///
1319 /// # Examples
1320 ///
1321 /// ```should_panic
1322 /// use astack::stack;
1323 ///
1324 /// let mut stack = stack! {
1325 /// [String; 3] = ["data1".into(), "data2".into(), "data3".into()]
1326 /// };
1327 /// let data = stack.cut_panicking::<2>();
1328 /// assert_eq!(data, ["data2".to_string(), "data3".to_string()]);
1329 /// assert_eq!(stack.tos(), Some(&String::from("data1")));
1330 ///
1331 /// // The following operation panics at runtime!
1332 /// let _ = stack.cut_panicking::<2>();
1333 /// ```
1334 #[inline]
1335 #[must_use = "If you want to discard the result, see `Stack::truncate_panicking`"]
1336 pub fn cut_panicking<const M: usize>(&mut self) -> [T; M] {
1337 assert!(
1338 M <= self.len,
1339 "Called Stack::cut_panicking but M > self.len"
1340 );
1341 unsafe { self.cut_unchecked() }
1342 }
1343
1344 /// Pops `M` items from the stack and returns them as an array (no dynamic
1345 /// allocation is involved) without checking if there are enough items.
1346 /// The order of the items is preserved: the stack is literally 'cut'.
1347 ///
1348 /// # Safety
1349 ///
1350 /// If `M > stack.len`, i.e., the requested number of
1351 /// items exceeds the number of items available, *[undefined behavior]* occurs.
1352 ///
1353 /// # Examples
1354 ///
1355 /// ```
1356 /// use astack::stack;
1357 ///
1358 /// let mut stack = stack! {
1359 /// [i64; 8] = [89, 34, 56, 78, 12, 90, 78, 67]
1360 /// };
1361 ///
1362 /// let last_three_numbers = unsafe { stack.cut_unchecked::<3>() };
1363 /// assert_eq!(last_three_numbers, [90, 78, 67]);
1364 /// assert_eq!(stack, [89, 34, 56, 78, 12]);
1365 ///
1366 /// // The following operation would result in undefined behavior, as there are
1367 /// // only 5 items remaining in the stack.
1368 /// // let _ = unsafe { stack.cut_unchecked::<6>() };
1369 /// ```
1370 ///
1371 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1372 #[inline]
1373 #[must_use = "If you want to discard the result, see `Stack::truncate_unchecked`"]
1374 pub unsafe fn cut_unchecked<const M: usize>(&mut self) -> [T; M] {
1375 debug_assert!(M <= self.len);
1376
1377 unsafe {
1378 // SAFETY: The `assume_init` is safe because the type we are claiming
1379 // to have initialized here is a bunch of `MaybeUninit`s, which do not
1380 // require initialization.
1381 // https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
1382 let mut arr = mem::MaybeUninit::<[mem::MaybeUninit<T>; M]>::uninit().assume_init();
1383
1384 // SAFETY: this is similar to slice::swap_with_slice. The slices cannot
1385 // overlap because mutable references are exclusive.
1386 ptr::swap_nonoverlapping(
1387 self.items[(self.len - M)..].as_mut_ptr(),
1388 arr[..].as_mut_ptr(),
1389 M,
1390 );
1391 self.len -= M;
1392
1393 // SAFETY: At this point all the items inside arr have been swapped with
1394 // initialized data.
1395 arr.map(|item| item.assume_init())
1396 }
1397 }
1398
1399 /// Swaps TOS with `item`, returning the previous TOS.
1400 ///
1401 /// # Errors
1402 ///
1403 /// If the stack is empty, [`StackError`] is returned instead.
1404 ///
1405 /// # Examples
1406 ///
1407 /// ```
1408 /// use astack::stack;
1409 ///
1410 /// let mut stack = stack! {
1411 /// [&str; 10] = ["praise", "Lamborghini", "supercars!"]
1412 /// };
1413 ///
1414 /// // Replace "supercars" with "tractors".
1415 /// if let Ok(old_tos) = stack.swap_tos("tractors") {
1416 /// println!("The old tos was: {}", old_tos);
1417 /// assert_eq!(old_tos, "supercars!");
1418 /// } else {
1419 /// println!("Could not swap tos: empty stack!");
1420 /// }
1421 /// ```
1422 #[inline]
1423 pub fn swap_tos(&mut self, item: T) -> Result<T, StackError> {
1424 if self.is_empty() {
1425 Err(StackError::Underflow)
1426 } else {
1427 Ok(unsafe { self.swap_tos_unchecked(item) })
1428 }
1429 }
1430
1431 /// Swaps TOS with `item`, returning the previous TOS.
1432 ///
1433 /// # Panics
1434 ///
1435 /// Panics if the stack is empty.
1436 ///
1437 /// # Examples
1438 ///
1439 /// ```
1440 /// use astack::stack;
1441 ///
1442 /// let mut stack = stack![i64; 9];
1443 ///
1444 /// // SAFETY: We know there's enough space to do it.
1445 /// unsafe {
1446 /// stack.push_unchecked(81);
1447 /// stack.push_unchecked(3);
1448 /// }
1449 ///
1450 /// // This will panic if the stack is empty!
1451 /// assert_eq!(stack.swap_tos_panicking(16), 3);
1452 /// assert_eq!(stack.swap_tos_panicking(25), 16);
1453 /// assert_eq!(stack, stack! {
1454 /// [i64; 9] = [81, 25]
1455 /// });
1456 /// ```
1457 #[inline]
1458 pub fn swap_tos_panicking(&mut self, item: T) -> T {
1459 assert!(
1460 !self.is_empty(),
1461 "Called Stack::swap_tos_panicking but the stack is empty"
1462 );
1463 unsafe { self.swap_tos_unchecked(item) }
1464 }
1465
1466 /// Swaps TOS with `item`, returning the previous TOS without checking whether
1467 /// the stack is empty or not. For a safe alternative, see [`swap_tos`][Stack::swap_tos]
1468 /// or [`swap_tos_panicking`][Stack::swap_tos_panicking].
1469 ///
1470 /// # Safety
1471 ///
1472 /// Calling this method if the stack is empty is *[undefined behavior]*.
1473 ///
1474 /// # Examples
1475 ///
1476 /// ```
1477 /// use astack::stack;
1478 ///
1479 /// // A stack full of &str.
1480 /// let mut stack = stack! {
1481 /// [&str; 2] = ["yeet", "lmao"]
1482 /// };
1483 ///
1484 /// // SAFETY: we know that the stack is not empty at this point.
1485 /// let old_tos = unsafe {
1486 /// stack.swap_tos_unchecked("lolxd")
1487 /// };
1488 ///
1489 /// assert_eq!(old_tos, "lmao");
1490 /// assert_eq!(stack.tos(), Some(&"lolxd"));
1491 /// ```
1492 ///
1493 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1494 #[inline]
1495 pub unsafe fn swap_tos_unchecked(&mut self, item: T) -> T {
1496 debug_assert!(!self.is_empty());
1497
1498 unsafe {
1499 // SAFETY: the user has assured us that there is an item to be swapped,
1500 // and that `item` won't point to garbage.
1501 let item = ptr::replace(
1502 self.items.as_mut_ptr().add(self.len - 1),
1503 mem::MaybeUninit::new(item),
1504 );
1505
1506 // SAFETY: the item has been correctly initialized at this point.
1507 item.assume_init()
1508 }
1509 }
1510
1511 /// Swaps TOS with TOS - 1. In other terms, swaps the topmost item of the stack
1512 /// with the one immediately below it.
1513 ///
1514 /// # Errors
1515 ///
1516 /// If the stack contains less than two items, [`StackError`] is
1517 /// returned.
1518 ///
1519 /// # Examples
1520 ///
1521 /// ```
1522 /// use astack::{stack, StackError};
1523 ///
1524 /// let mut stack1 = stack! {
1525 /// [char; 10] = ['a', 'b']
1526 /// };
1527 ///
1528 /// stack1.rotate_tos().unwrap();
1529 /// assert_eq!(stack1.tos(), Some(&'a'));
1530 ///
1531 /// // Create a stack with no items.
1532 /// let mut stack2 = stack![i32; 5];
1533 /// assert_eq!(stack2.rotate_tos(), Err(StackError::Underflow));
1534 /// ```
1535 #[inline]
1536 pub fn rotate_tos(&mut self) -> Result<(), StackError> {
1537 if self.len < 2 {
1538 Err(StackError::Underflow)
1539 } else {
1540 unsafe { self.rotate_tos_unchecked() };
1541 Ok(())
1542 }
1543 }
1544
1545 /// Swaps TOS with TOS - 1. In other terms, swaps the topmost item of the stack
1546 /// with the one immediately below it.
1547 ///
1548 /// # Panics
1549 ///
1550 /// Panics if the stack contains less than 2 items.
1551 ///
1552 /// # Examples
1553 ///
1554 /// ```
1555 /// use astack::stack;
1556 ///
1557 /// let mut stack = stack! {
1558 /// [isize; 5] = [90, 10, 30]
1559 /// };
1560 ///
1561 /// // This would panic if there were less than 2 items!
1562 /// stack.rotate_tos_panicking();
1563 /// assert_eq!(stack.tos(), Some(&10));
1564 ///
1565 /// // Rotate again!
1566 /// stack.rotate_tos_panicking();
1567 ///
1568 /// // Now the tos has been swapped twice.
1569 /// assert_eq!(stack.tos(), Some(&30));
1570 /// ```
1571 #[inline]
1572 pub fn rotate_tos_panicking(&mut self) {
1573 assert!(
1574 self.len >= 2,
1575 "Called Stack::rotate_tos_panicking but the stack contains 1 or 0 items"
1576 );
1577 unsafe { self.rotate_tos_unchecked() };
1578 }
1579
1580 /// Swaps TOS with TOS - 1. In other terms, swaps the topmost item of the stack
1581 /// with the one immediately below it, without checking if the stack contains
1582 /// at least 2 items.
1583 ///
1584 /// # Safety
1585 ///
1586 /// Calling this method if the stack is contains less than 2 items
1587 /// is *[undefined behavior]*.
1588 ///
1589 /// # Examples
1590 ///
1591 /// ```
1592 /// use astack::stack;
1593 ///
1594 /// let mut stack = stack! {
1595 /// [char; 80] = ['7', '8', '9']
1596 /// };
1597 ///
1598 /// // SAFETY: we know there are at least 2 items at this point.
1599 /// unsafe {
1600 /// stack.rotate_tos_unchecked();
1601 /// }
1602 ///
1603 /// assert_eq!(stack.tos(), Some(&'8'));
1604 /// ```
1605 ///
1606 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1607 #[inline]
1608 pub unsafe fn rotate_tos_unchecked(&mut self) {
1609 debug_assert!(self.len >= 2);
1610
1611 // SAFETY: this is similar to slice::swap_unchecked.
1612 // Create only 1 single ptr (this is important!)
1613 let ptr = self.items.as_mut_ptr();
1614 unsafe {
1615 ptr::swap(ptr.add(self.len - 1), ptr.add(self.len - 2));
1616 }
1617 }
1618
1619 /// Shortens the stack, keeping the `len` elements and dropping
1620 /// the rest. If `len == stack.len`, nothing happens.
1621 ///
1622 /// # Errors
1623 ///
1624 /// Returns a [`StackError`] if `len > stack.len`.
1625 ///
1626 /// # Examples
1627 ///
1628 /// ```
1629 /// use astack::{stack, StackError};
1630 ///
1631 /// let mut stack = stack! {
1632 /// [i8; 5] = [8, 3, 0]
1633 /// };
1634 ///
1635 /// // Remove 2 items, we don't need them!
1636 ///
1637 /// assert!(stack.truncate(2).is_ok());
1638 /// // There are not enough items to truncate!
1639 /// assert_eq!(stack.truncate(3), Err(StackError::Underflow));
1640 /// assert_eq!(stack.len(), 2);
1641 /// ```
1642 #[inline]
1643 pub fn truncate(&mut self, new_len: usize) -> Result<(), StackError> {
1644 if new_len > self.len {
1645 Err(StackError::Underflow)
1646 } else {
1647 unsafe { self.truncate_unchecked(new_len) };
1648 Ok(())
1649 }
1650 }
1651
1652 /// Shortens the stack, keeping the `len` elements and dropping
1653 /// the rest. If `len == stack.len`, nothing happens.
1654 ///
1655 /// # Panics
1656 ///
1657 /// Panics if `len > stack.len`.
1658 ///
1659 /// # Examples
1660 ///
1661 /// ```should_panic
1662 /// use astack::stack;
1663 ///
1664 /// let mut stack = stack! {
1665 /// [i8; 5] = [8, 3, 0]
1666 /// };
1667 ///
1668 /// // Keep 2 items, we don't need them!
1669 ///
1670 /// stack.truncate_panicking(2);
1671 /// // When the following line is executed, the program panics, as there are not
1672 /// // enough items to remove!
1673 /// stack.truncate_panicking(3);
1674 /// ```
1675 #[inline]
1676 pub fn truncate_panicking(&mut self, new_len: usize) {
1677 assert!(
1678 new_len <= self.len,
1679 "Called Stack::truncate_panicking but `len` ({}) is greater than stack's len ({})",
1680 new_len,
1681 self.len
1682 );
1683 unsafe { self.truncate_unchecked(new_len) };
1684 }
1685
1686 /// Shortens the stack, keeping the `len` elements and dropping
1687 /// the rest. If `len == stack.len`, nothing happens. Does not check for the
1688 /// validity of `len`.
1689 ///
1690 /// # Safety
1691 ///
1692 /// If `len > stack.len`, *[undefined behavior]* occurs.
1693 ///
1694 /// # Examples
1695 ///
1696 /// ```
1697 /// use astack::{stack, Stack};
1698 ///
1699 /// // Create a function which removes all items from the stack!
1700 /// // This uses unsafe code but it is safe.
1701 ///
1702 /// fn truncate_all_items<T, const N: usize>(stack: &mut Stack<T, N>) {
1703 /// unsafe { stack.truncate_unchecked(0) };
1704 /// }
1705 ///
1706 /// let mut stack = stack! {
1707 /// [i32; 8] = [6, 7, 8, 9, 0]
1708 /// };
1709 ///
1710 /// assert_eq!(stack.len(), 5);
1711 /// truncate_all_items(&mut stack);
1712 /// assert!(stack.is_empty());
1713 /// ```
1714 ///
1715 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1716 #[inline]
1717 pub unsafe fn truncate_unchecked(&mut self, new_len: usize) {
1718 debug_assert!(new_len <= self.len);
1719
1720 // SAFETY: the user gave us a valid len.
1721 let remaining_len = self.len - new_len;
1722 unsafe {
1723 self.drop_items(remaining_len);
1724 }
1725 self.len = new_len;
1726 }
1727
1728 /// Apply `f` to TOS, returning [`StackError`] if the stack is empty. `f` receives
1729 /// a mutable reference to TOS, which can be modified accordingly.
1730 ///
1731 /// # Errors
1732 ///
1733 /// The function returns a [`StackError`] if the stack is empty, because in that
1734 /// situation you could not apply `f` to TOS.
1735 ///
1736 /// # Examples
1737 ///
1738 /// ```
1739 /// use astack::{stack, StackError};
1740 ///
1741 /// fn double(x: &mut usize) {
1742 /// *x = *x * 2;
1743 /// }
1744 ///
1745 /// let mut stack = stack! {
1746 /// [usize; 10] = [7, 8, 9]
1747 /// };
1748 ///
1749 /// assert_eq!(stack.apply_tos(double), Ok(()));
1750 /// assert_eq!(stack.tos(), Some(&18));
1751 ///
1752 /// // Let's try this on an empty stack...
1753 ///
1754 /// let mut empty_stack = stack![usize; 10];
1755 /// assert_eq!(empty_stack.apply_tos(double), Err(StackError::Underflow));
1756 /// ```
1757 #[inline]
1758 pub fn apply_tos<F>(&mut self, f: F) -> Result<(), StackError>
1759 where
1760 F: Fn(&mut T),
1761 {
1762 let Some(tos) = self.tos_mut() else {
1763 return Err(StackError::Underflow);
1764 };
1765
1766 f(tos);
1767 Ok(())
1768 }
1769
1770 /// Apply `f` to TOS, panicking if the stack is empty. `f` receives
1771 /// a mutable reference to TOS, which can be modified accordingly.
1772 ///
1773 /// # Examples
1774 ///
1775 /// ```should_panic
1776 /// use astack::stack;
1777 ///
1778 /// let mut names = stack! {
1779 /// [String; 4] = ["Frank".to_string(), "Joe".to_string()]
1780 /// };
1781 ///
1782 /// names.apply_tos_panicking(|name| {
1783 /// name.push('!');
1784 /// });
1785 /// assert_eq!(names.tos(), Some(&String::from("Joe!")));
1786 ///
1787 /// names.clear();
1788 ///
1789 /// // The program panics because there is no TOS here!
1790 /// names.apply_tos_panicking(|name| { name.push('!'); });
1791 /// ```
1792 #[inline]
1793 pub fn apply_tos_panicking<F>(&mut self, f: F)
1794 where
1795 F: Fn(&mut T),
1796 {
1797 assert!(
1798 !self.is_empty(),
1799 "Called Stack::apply_tos_panicking on empty stack"
1800 );
1801 unsafe {
1802 self.apply_tos_unchecked(f);
1803 }
1804 }
1805
1806 /// Apply `f` to TOS, without checking whether the stack is empty or not.
1807 /// `f` receives a mutable reference to TOS, which can be modified accordingly.
1808 ///
1809 /// # Safety
1810 ///
1811 /// Calling this method on an empty stack is *[undefined behaviour]*. Refer to
1812 /// [apply_tos][Stack::apply_tos] and [apply_tos_panicking][Stack::apply_tos_panicking]
1813 /// for a safe version of this function.
1814 ///
1815 /// # Examples
1816 ///
1817 /// ```
1818 /// use astack::Stack;
1819 ///
1820 /// fn create_a_non_empty_stack() -> Stack<i32, 16> {
1821 /// Stack::fill_with_default()
1822 /// }
1823 ///
1824 /// let mut stack = create_a_non_empty_stack();
1825 ///
1826 /// // Safety: we know that the function never returns an empty stack.
1827 /// // It is therefore safe to call `apply_tos_unchecked` here.
1828 /// let set_to_max = |num: &mut i32| *num = i32::MAX;
1829 /// unsafe {
1830 /// stack.apply_tos_unchecked(set_to_max);
1831 /// }
1832 /// assert_eq!(stack.tos(), Some(&i32::MAX));
1833 /// ```
1834 ///
1835 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1836 #[inline]
1837 pub unsafe fn apply_tos_unchecked<F>(&mut self, f: F)
1838 where
1839 F: Fn(&mut T),
1840 {
1841 debug_assert!(!self.is_empty());
1842
1843 // SAFETY: the user is upholding the safety contract here by promising
1844 // that the stack is not empty.
1845 f(unsafe { self.tos_mut_unchecked() });
1846 }
1847
1848 /// Removes all the initialized items contained in the stack. The `len` becomes
1849 /// 0.
1850 ///
1851 /// # Examples
1852 ///
1853 /// ```
1854 /// use astack::stack;
1855 ///
1856 /// let mut stack = stack! {
1857 /// [u64; 128] = [7, 8, 9, 10]
1858 /// };
1859 /// assert!(!stack.is_empty());
1860 ///
1861 /// // Remove all the stack items.
1862 /// stack.clear();
1863 /// assert!(stack.is_empty());
1864 /// ```
1865 #[inline]
1866 pub fn clear(&mut self) {
1867 // SAFETY: the items have been correctly initialized, this SHOULD not
1868 // result in a double free (unless user-provied incorrect initialization).
1869 unsafe { self.drop_items(0) };
1870 self.len = 0;
1871 }
1872
1873 /// The implementation of [`Drop::drop`] for [`Stack`].
1874 #[inline]
1875 unsafe fn drop_items(&mut self, start: usize) {
1876 // SAFETY: mem::MaybeUninit<T> has the same memory layout and align as T,
1877 // as it is #[repr(transparent)]. We assume that self.items[..self.len]
1878 // have been correctly initialized: if this is not the case, we drop
1879 // uninit memory, which is bad I suppose. But the user had been warned!
1880 //
1881 // We take inspiration from the Drop implementation of Vec<T> and from
1882 // the link below.
1883 //
1884 // https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.slice_assume_init_mut
1885 unsafe {
1886 let items = self.init_items_as_mut_ptr(start);
1887 ptr::drop_in_place(items);
1888 }
1889 }
1890
1891 /// Returns an immutable raw pointer to a slice of initialized items, beginning
1892 /// from `start`. If `start` is 0, this will return all the initialized items.
1893 #[inline]
1894 unsafe fn init_items_as_ptr(&self, start: usize) -> *const [T] {
1895 debug_assert!(start <= self.len);
1896
1897 // SAFETY: this is only called internally and we know what we are doing.
1898 unsafe { self.items.get_unchecked(start..self.len) as *const [mem::MaybeUninit<T>] as _ }
1899 }
1900
1901 /// Returns a mutable raw pointer to a slice of initialized items, beginning
1902 /// from `start`. If `start` is 0, this will return all the initialized items.
1903 #[inline]
1904 unsafe fn init_items_as_mut_ptr(&mut self, start: usize) -> *mut [T] {
1905 debug_assert!(start <= self.len);
1906
1907 // SAFETY: this is only called internally and we know what we are doing.
1908 unsafe { self.items.get_unchecked_mut(start..self.len) as *mut [mem::MaybeUninit<T>] as _ }
1909 }
1910}
1911
1912impl<T, const N: usize> Default for Stack<T, N> {
1913 /// `Stack::<T, N>::default()` is equivalent to `Stack::<T, N>::new()`.
1914 #[inline]
1915 fn default() -> Self {
1916 Self::new()
1917 }
1918}
1919
1920impl<T, const N: usize> Clone for Stack<T, N>
1921where
1922 T: Clone,
1923{
1924 #[inline]
1925 fn clone(&self) -> Self {
1926 // Create an array of uninitialized memory and fill each uninitialized
1927 // cell with a copy of the corresponding initialized item.
1928 unsafe {
1929 let mut items = mem::MaybeUninit::<[mem::MaybeUninit<T>; N]>::uninit().assume_init();
1930 self.items
1931 .get_unchecked(..self.len)
1932 .iter()
1933 .zip(items.get_unchecked_mut(..self.len))
1934 .for_each(|(src, dst)| {
1935 dst.write(src.assume_init_ref().clone());
1936 });
1937 Self {
1938 items,
1939 len: self.len,
1940 }
1941 }
1942 }
1943}
1944
1945impl<T, U, const N: usize> PartialEq<Stack<U, N>> for Stack<T, N>
1946where
1947 T: PartialEq<U>,
1948{
1949 #[inline]
1950 fn eq(&self, other: &Stack<U, N>) -> bool {
1951 unsafe {
1952 let items1 = self.init_items_as_ptr(0);
1953 let items2 = other.init_items_as_ptr(0);
1954
1955 // SAFETY: the following items should have been correctly initialized
1956 *items1 == *items2
1957 }
1958 }
1959}
1960
1961impl<T, U, const N: usize> PartialEq<[U]> for Stack<T, N>
1962where
1963 T: PartialEq<U>,
1964{
1965 #[inline]
1966 fn eq(&self, other: &[U]) -> bool {
1967 unsafe {
1968 let items = self.init_items_as_ptr(0);
1969 *items == *other
1970 }
1971 }
1972}
1973
1974impl<T, U, const N: usize, const M: usize> PartialEq<[U; M]> for Stack<T, N>
1975where
1976 T: PartialEq<U>,
1977{
1978 #[inline]
1979 fn eq(&self, other: &[U; M]) -> bool {
1980 unsafe {
1981 let items = self.init_items_as_ptr(0);
1982 *items == *other
1983 }
1984 }
1985}
1986
1987impl<T, const N: usize> hash::Hash for Stack<T, N>
1988where
1989 T: hash::Hash,
1990{
1991 #[inline]
1992 fn hash<H>(&self, state: &mut H)
1993 where
1994 H: hash::Hasher,
1995 {
1996 ptr::hash(unsafe { self.init_items_as_ptr(0) }, state);
1997 }
1998}
1999
2000impl<T, const N: usize> fmt::Debug for Stack<T, N>
2001where
2002 T: fmt::Debug,
2003{
2004 #[inline]
2005 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2006 // Better print output
2007 struct DebugUninit;
2008 impl fmt::Debug for DebugUninit {
2009 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2010 write!(f, "(uninit)")
2011 }
2012 }
2013
2014 let mut list = f.debug_list();
2015
2016 unsafe {
2017 list.entries(
2018 self.items
2019 .get_unchecked(..self.len)
2020 .iter()
2021 .map(|item| item.assume_init_ref()),
2022 );
2023 }
2024
2025 list.entries((self.len..N).map(|_| &DebugUninit));
2026
2027 list.finish()
2028 }
2029}
2030
2031impl<T, const N: usize> Drop for Stack<T, N> {
2032 #[inline]
2033 fn drop(&mut self) {
2034 unsafe { self.drop_items(0) };
2035 }
2036}
2037
2038#[cfg(feature = "std")]
2039impl<T, const N: usize> From<Stack<T, N>> for std::vec::Vec<T> {
2040 #[inline]
2041 fn from(stack: Stack<T, N>) -> Self {
2042 let mut v = std::vec::Vec::with_capacity(stack.len());
2043 // We rev because we want the end of the vec to be the top
2044 // of the stack
2045 v.extend(stack.into_iter().rev());
2046 v
2047 }
2048}
2049
2050#[cfg(feature = "std")]
2051impl<T, const N: usize> TryFrom<std::vec::Vec<T>> for Stack<T, N> {
2052 type Error = StackError;
2053
2054 #[inline]
2055 fn try_from(v: std::vec::Vec<T>) -> Result<Self, Self::Error> {
2056 try_extend_into_iter(v.len(), v)
2057 }
2058}
2059
2060#[cfg(feature = "std")]
2061impl<T, const N: usize> TryFrom<std::collections::LinkedList<T>> for Stack<T, N> {
2062 type Error = StackError;
2063
2064 #[inline]
2065 fn try_from(list: std::collections::LinkedList<T>) -> Result<Self, Self::Error> {
2066 try_extend_into_iter(list.len(), list)
2067 }
2068}
2069
2070#[cfg(feature = "std")]
2071#[inline]
2072fn try_extend_into_iter<T, const N: usize>(
2073 len: usize,
2074 it: impl IntoIterator<Item = T>,
2075) -> Result<Stack<T, N>, StackError> {
2076 if len > N {
2077 return Err(StackError::Overflow);
2078 }
2079
2080 let mut stack = Stack::new();
2081
2082 // SAFETY: we know that the iterator does not have more items
2083 // than the stack's remaining capacity
2084 unsafe {
2085 stack.extend_unchecked(it);
2086 }
2087 Ok(stack)
2088}
2089
2090impl<T, const N: usize> IntoIterator for Stack<T, N> {
2091 type IntoIter = StackIntoIter<T, N>;
2092 type Item = T;
2093
2094 #[inline]
2095 fn into_iter(mut self) -> Self::IntoIter {
2096 // Replace the items with the default array
2097 //
2098 // SAFETY: same as `Stack::new()`
2099 let items = mem::replace(&mut self.items, unsafe {
2100 mem::MaybeUninit::uninit().assume_init()
2101 });
2102
2103 // Do not forget to reset the length as well otherwise we drop more than we have!
2104 let top_len = mem::replace(&mut self.len, 0);
2105
2106 // Safety: `items` and `top_len` are valid as they come from us
2107 unsafe { StackIntoIter::new(items, top_len) }
2108 }
2109}