mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-28 04:50:34 +00:00
Implements TryFrom for Deque from array
This commit is contained in:
parent
f974fc129c
commit
75dbe63466
@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
- Implement `Default` for `CapacityError`.
|
||||
- Implement `defmt::Format` for `CapacityError`.
|
||||
- Implement `TryFrom` for `Deque` from array.
|
||||
|
||||
## [v0.9.1] - 2025-08-19
|
||||
|
||||
|
139
src/deque.rs
139
src/deque.rs
@ -33,15 +33,15 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage};
|
||||
use crate::CapacityError;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::iter::FusedIterator;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
use core::{ptr, slice};
|
||||
|
||||
use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage};
|
||||
|
||||
/// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`].
|
||||
///
|
||||
/// In most cases you should use [`Deque`] or [`DequeView`] directly. Only use this
|
||||
@ -999,11 +999,55 @@ impl<T: PartialEq, const N: usize> PartialEq for Deque<T, N> {
|
||||
|
||||
impl<T: Eq, const N: usize> Eq for Deque<T, N> {}
|
||||
|
||||
impl<T, const NS: usize, const ND: usize> TryFrom<[T; NS]> for Deque<T, ND> {
|
||||
/// Converts a `[T; NS]` into a `Deque<T, ND>`.
|
||||
///
|
||||
/// ```
|
||||
/// use heapless::Deque;
|
||||
///
|
||||
/// let deq1 = Deque::<u8, 5>::try_from([1, 2, 3]).unwrap();
|
||||
/// let mut deq2 = Deque::<u8, 5>::new();
|
||||
/// deq2.push_back(1).unwrap();
|
||||
/// deq2.push_back(2).unwrap();
|
||||
/// deq2.push_back(3).unwrap();
|
||||
///
|
||||
/// assert_eq!(deq1, deq2);
|
||||
/// ```
|
||||
type Error = (CapacityError, [T; NS]);
|
||||
|
||||
/// Converts a `[T; NS]` array into a `Deque<T, ND>`.
|
||||
///
|
||||
/// Returns back the `value` if NS > ND.
|
||||
fn try_from(value: [T; NS]) -> Result<Self, Self::Error> {
|
||||
if NS > ND {
|
||||
return Err((CapacityError, value));
|
||||
}
|
||||
|
||||
let mut deq = Self::default();
|
||||
let value = ManuallyDrop::new(value);
|
||||
|
||||
// SAFETY: We already ensured that value fits in deq.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
value.as_ptr(),
|
||||
deq.buffer.buffer.as_mut_ptr().cast::<T>(),
|
||||
NS,
|
||||
);
|
||||
}
|
||||
|
||||
deq.front = 0;
|
||||
deq.back = NS;
|
||||
deq.full = NS == ND;
|
||||
|
||||
Ok(deq)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use static_assertions::assert_not_impl_any;
|
||||
|
||||
use super::Deque;
|
||||
use crate::CapacityError;
|
||||
use static_assertions::assert_not_impl_any;
|
||||
|
||||
// Ensure a `Deque` containing `!Send` values stays `!Send` itself.
|
||||
assert_not_impl_any!(Deque<*const (), 4>: Send);
|
||||
@ -1545,4 +1589,89 @@ mod tests {
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_array() {
|
||||
// Array is too big error.
|
||||
assert!(matches!(
|
||||
Deque::<u8, 3>::try_from([1, 2, 3, 4]),
|
||||
Err((CapacityError, [1, 2, 3, 4]))
|
||||
));
|
||||
|
||||
// Array is at limit.
|
||||
let deq1 = Deque::<u8, 3>::try_from([1, 2, 3]).unwrap();
|
||||
let mut deq2 = Deque::<u8, 3>::new();
|
||||
deq2.push_back(1).unwrap();
|
||||
deq2.push_back(2).unwrap();
|
||||
deq2.push_back(3).unwrap();
|
||||
assert!(deq1.is_full());
|
||||
assert_eq!(deq1, deq2);
|
||||
|
||||
// Array is under limit.
|
||||
let deq1 = Deque::<u8, 8>::try_from([1, 2, 3, 4]).unwrap();
|
||||
let mut deq2 = Deque::<u8, 8>::new();
|
||||
deq2.push_back(1).unwrap();
|
||||
deq2.push_back(2).unwrap();
|
||||
deq2.push_back(3).unwrap();
|
||||
deq2.push_back(4).unwrap();
|
||||
|
||||
assert!(!deq1.is_full());
|
||||
assert_eq!(deq1, deq2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_array_with_zst() {
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
struct ZeroSizedType;
|
||||
|
||||
// Test with ZST (zero-sized type)
|
||||
let deq1 =
|
||||
Deque::<ZeroSizedType, 5>::try_from([ZeroSizedType, ZeroSizedType, ZeroSizedType])
|
||||
.unwrap();
|
||||
let mut deq2 = Deque::<ZeroSizedType, 5>::new();
|
||||
deq2.push_back(ZeroSizedType).unwrap();
|
||||
deq2.push_back(ZeroSizedType).unwrap();
|
||||
deq2.push_back(ZeroSizedType).unwrap();
|
||||
|
||||
assert_eq!(deq1, deq2);
|
||||
assert_eq!(deq1.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_array_drop() {
|
||||
droppable!();
|
||||
|
||||
// Array is over limit.
|
||||
{
|
||||
let _result = Deque::<Droppable, 2>::try_from([
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
]);
|
||||
}
|
||||
|
||||
assert_eq!(Droppable::count(), 0);
|
||||
|
||||
// Array is at limit.
|
||||
{
|
||||
let _result = Deque::<Droppable, 3>::try_from([
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
]);
|
||||
}
|
||||
|
||||
assert_eq!(Droppable::count(), 0);
|
||||
|
||||
// Array is under limit.
|
||||
{
|
||||
let _result = Deque::<Droppable, 4>::try_from([
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
Droppable::new(),
|
||||
]);
|
||||
}
|
||||
|
||||
assert_eq!(Droppable::count(), 0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user