Skip to content

Commit ae6e2ab

Browse files
authored
Merge pull request #591 from dysonltd/impl_try_from_for_deque
Implements TryFrom for Deque from array
2 parents f974fc1 + 75dbe63 commit ae6e2ab

File tree

2 files changed

+135
-5
lines changed

2 files changed

+135
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212

1313
- Implement `Default` for `CapacityError`.
1414
- Implement `defmt::Format` for `CapacityError`.
15+
- Implement `TryFrom` for `Deque` from array.
1516

1617
## [v0.9.1] - 2025-08-19
1718

src/deque.rs

Lines changed: 134 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@
3333
//! }
3434
//! ```
3535
36+
use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage};
37+
use crate::CapacityError;
3638
use core::cmp::Ordering;
3739
use core::fmt;
3840
use core::iter::FusedIterator;
3941
use core::marker::PhantomData;
40-
use core::mem::MaybeUninit;
42+
use core::mem::{ManuallyDrop, MaybeUninit};
4143
use core::{ptr, slice};
4244

43-
use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage};
44-
4545
/// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`].
4646
///
4747
/// 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> {
999999

10001000
impl<T: Eq, const N: usize> Eq for Deque<T, N> {}
10011001

1002+
impl<T, const NS: usize, const ND: usize> TryFrom<[T; NS]> for Deque<T, ND> {
1003+
/// Converts a `[T; NS]` into a `Deque<T, ND>`.
1004+
///
1005+
/// ```
1006+
/// use heapless::Deque;
1007+
///
1008+
/// let deq1 = Deque::<u8, 5>::try_from([1, 2, 3]).unwrap();
1009+
/// let mut deq2 = Deque::<u8, 5>::new();
1010+
/// deq2.push_back(1).unwrap();
1011+
/// deq2.push_back(2).unwrap();
1012+
/// deq2.push_back(3).unwrap();
1013+
///
1014+
/// assert_eq!(deq1, deq2);
1015+
/// ```
1016+
type Error = (CapacityError, [T; NS]);
1017+
1018+
/// Converts a `[T; NS]` array into a `Deque<T, ND>`.
1019+
///
1020+
/// Returns back the `value` if NS > ND.
1021+
fn try_from(value: [T; NS]) -> Result<Self, Self::Error> {
1022+
if NS > ND {
1023+
return Err((CapacityError, value));
1024+
}
1025+
1026+
let mut deq = Self::default();
1027+
let value = ManuallyDrop::new(value);
1028+
1029+
// SAFETY: We already ensured that value fits in deq.
1030+
unsafe {
1031+
ptr::copy_nonoverlapping(
1032+
value.as_ptr(),
1033+
deq.buffer.buffer.as_mut_ptr().cast::<T>(),
1034+
NS,
1035+
);
1036+
}
1037+
1038+
deq.front = 0;
1039+
deq.back = NS;
1040+
deq.full = NS == ND;
1041+
1042+
Ok(deq)
1043+
}
1044+
}
1045+
10021046
#[cfg(test)]
10031047
mod tests {
1004-
use static_assertions::assert_not_impl_any;
1005-
10061048
use super::Deque;
1049+
use crate::CapacityError;
1050+
use static_assertions::assert_not_impl_any;
10071051

10081052
// Ensure a `Deque` containing `!Send` values stays `!Send` itself.
10091053
assert_not_impl_any!(Deque<*const (), 4>: Send);
@@ -1545,4 +1589,89 @@ mod tests {
15451589

15461590
assert_eq!(a, b);
15471591
}
1592+
1593+
#[test]
1594+
fn try_from_array() {
1595+
// Array is too big error.
1596+
assert!(matches!(
1597+
Deque::<u8, 3>::try_from([1, 2, 3, 4]),
1598+
Err((CapacityError, [1, 2, 3, 4]))
1599+
));
1600+
1601+
// Array is at limit.
1602+
let deq1 = Deque::<u8, 3>::try_from([1, 2, 3]).unwrap();
1603+
let mut deq2 = Deque::<u8, 3>::new();
1604+
deq2.push_back(1).unwrap();
1605+
deq2.push_back(2).unwrap();
1606+
deq2.push_back(3).unwrap();
1607+
assert!(deq1.is_full());
1608+
assert_eq!(deq1, deq2);
1609+
1610+
// Array is under limit.
1611+
let deq1 = Deque::<u8, 8>::try_from([1, 2, 3, 4]).unwrap();
1612+
let mut deq2 = Deque::<u8, 8>::new();
1613+
deq2.push_back(1).unwrap();
1614+
deq2.push_back(2).unwrap();
1615+
deq2.push_back(3).unwrap();
1616+
deq2.push_back(4).unwrap();
1617+
1618+
assert!(!deq1.is_full());
1619+
assert_eq!(deq1, deq2);
1620+
}
1621+
1622+
#[test]
1623+
fn try_from_array_with_zst() {
1624+
#[derive(Debug, PartialEq, Copy, Clone)]
1625+
struct ZeroSizedType;
1626+
1627+
// Test with ZST (zero-sized type)
1628+
let deq1 =
1629+
Deque::<ZeroSizedType, 5>::try_from([ZeroSizedType, ZeroSizedType, ZeroSizedType])
1630+
.unwrap();
1631+
let mut deq2 = Deque::<ZeroSizedType, 5>::new();
1632+
deq2.push_back(ZeroSizedType).unwrap();
1633+
deq2.push_back(ZeroSizedType).unwrap();
1634+
deq2.push_back(ZeroSizedType).unwrap();
1635+
1636+
assert_eq!(deq1, deq2);
1637+
assert_eq!(deq1.len(), 3);
1638+
}
1639+
1640+
#[test]
1641+
fn try_from_array_drop() {
1642+
droppable!();
1643+
1644+
// Array is over limit.
1645+
{
1646+
let _result = Deque::<Droppable, 2>::try_from([
1647+
Droppable::new(),
1648+
Droppable::new(),
1649+
Droppable::new(),
1650+
]);
1651+
}
1652+
1653+
assert_eq!(Droppable::count(), 0);
1654+
1655+
// Array is at limit.
1656+
{
1657+
let _result = Deque::<Droppable, 3>::try_from([
1658+
Droppable::new(),
1659+
Droppable::new(),
1660+
Droppable::new(),
1661+
]);
1662+
}
1663+
1664+
assert_eq!(Droppable::count(), 0);
1665+
1666+
// Array is under limit.
1667+
{
1668+
let _result = Deque::<Droppable, 4>::try_from([
1669+
Droppable::new(),
1670+
Droppable::new(),
1671+
Droppable::new(),
1672+
]);
1673+
}
1674+
1675+
assert_eq!(Droppable::count(), 0);
1676+
}
15481677
}

0 commit comments

Comments
 (0)