From 98afd95c9ad1800d9de69819d275838a4676c8ed Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Fri, 13 Dec 2024 16:19:44 +0000 Subject: [PATCH 01/12] Implemented TyrFrom for Deque from slice. --- CHANGELOG.md | 1 + src/deque.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec5966b63..128497cf18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `Deque::{swap, swap_unchecked, swap_remove_front, swap_remove_back}`. - Make `String::from_utf8_unchecked` const. - Implemented `PartialEq` and `Eq` for `Deque`. +- Implemented `TyrFrom` for `Deque` from slice. ### Changed diff --git a/src/deque.rs b/src/deque.rs index a9044158aa..341a53888d 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -37,7 +37,7 @@ 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}; @@ -998,6 +998,50 @@ impl PartialEq for Deque { impl Eq for Deque {} +impl TryFrom<[T; NS]> for Deque { + /// Converts a `[T; NS]` into a `Deque`. + /// + /// ``` + /// use heapless::Deque; + /// + /// let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); + /// let mut deq2 = Deque::::new(); + /// deq2.push_back(1).unwrap(); + /// deq2.push_back(2).unwrap(); + /// deq2.push_back(3).unwrap(); + /// deq2.push_back(4).unwrap(); + /// + /// // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. + /// assert_eq!(deq1.len(), deq2.len()); + /// for (i, e1) in deq1.iter().enumerate() { + /// assert_eq!(Some(e1), deq2.get(i)); + /// } + /// ``` + type Error = (); + + fn try_from(value: [T; NS]) -> Result { + if NS > ND { + return Err(()); + } + + let mut deq = Self::default(); + let value = ManuallyDrop::new(value); + + if size_of::() != 0 { + // SAFETY: We already ensured that value fits in deq. + unsafe { + ptr::copy_nonoverlapping(value.as_ptr(), deq.buffer.as_mut_ptr() as *mut 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; From 954aceea3174244106cdbccabe442f7756526100 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Mon, 16 Dec 2024 14:27:21 +0000 Subject: [PATCH 02/12] Added tests for the try_from slice method. --- src/deque.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/deque.rs b/src/deque.rs index 341a53888d..8f99703a2e 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1030,7 +1030,7 @@ impl TryFrom<[T; NS]> for Deque { if size_of::() != 0 { // SAFETY: We already ensured that value fits in deq. unsafe { - ptr::copy_nonoverlapping(value.as_ptr(), deq.buffer.as_mut_ptr() as *mut T, NS); + ptr::copy_nonoverlapping(value.as_ptr(), deq.buffer.buffer.as_mut_ptr() as *mut T, NS); } } @@ -1588,4 +1588,23 @@ mod tests { assert_eq!(a, b); } + + #[test] + fn tyr_from_slice() { + + assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); + + let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); + let mut deq2 = Deque::::new(); + deq2.push_back(1).unwrap(); + deq2.push_back(2).unwrap(); + deq2.push_back(3).unwrap(); + deq2.push_back(4).unwrap(); + + // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. + assert_eq!(deq1.len(), deq2.len()); + for (i, e1) in deq1.iter().enumerate() { + assert_eq!(Some(e1), deq2.get(i)); + } + } } From 1c58cf1de43e2af34f744aeb61275fbc0b382e83 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Mon, 16 Dec 2024 14:38:40 +0000 Subject: [PATCH 03/12] Fixed the style. --- src/deque.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/deque.rs b/src/deque.rs index 8f99703a2e..1cf4e82769 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1014,7 +1014,7 @@ impl TryFrom<[T; NS]> for Deque { /// // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. /// assert_eq!(deq1.len(), deq2.len()); /// for (i, e1) in deq1.iter().enumerate() { - /// assert_eq!(Some(e1), deq2.get(i)); + /// assert_eq!(Some(e1), deq2.get(i)); /// } /// ``` type Error = (); @@ -1591,7 +1591,6 @@ mod tests { #[test] fn tyr_from_slice() { - assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); @@ -1604,7 +1603,7 @@ mod tests { // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. assert_eq!(deq1.len(), deq2.len()); for (i, e1) in deq1.iter().enumerate() { - assert_eq!(Some(e1), deq2.get(i)); + assert_eq!(Some(e1), deq2.get(i)); } } } From d345c12b17590e4625031fe998f49153316a5ecf Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Mon, 6 Jan 2025 15:42:45 +0000 Subject: [PATCH 04/12] Fixed typo. --- src/deque.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deque.rs b/src/deque.rs index 1cf4e82769..4931edc93b 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1590,7 +1590,7 @@ mod tests { } #[test] - fn tyr_from_slice() { + fn tyr_from_array() { assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); From 4df18396126c627a5cc2327f9c361850469e2b30 Mon Sep 17 00:00:00 2001 From: William Date: Tue, 14 Jan 2025 11:51:24 +0000 Subject: [PATCH 05/12] Apply typo suggestions from code review Co-authored-by: Alex Martens --- CHANGELOG.md | 1 + src/deque.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 128497cf18..36cca4e645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Make `String::from_utf8_unchecked` const. - Implemented `PartialEq` and `Eq` for `Deque`. - Implemented `TyrFrom` for `Deque` from slice. +- Implemented `TryFrom` for `Deque` from slice. ### Changed diff --git a/src/deque.rs b/src/deque.rs index 4931edc93b..1e730c7056 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1590,7 +1590,7 @@ mod tests { } #[test] - fn tyr_from_array() { + fn try_from_array() { assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); From 88860f893037d93050ce336a66f2fbcc17bc2488 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Tue, 18 Feb 2025 14:21:35 +0000 Subject: [PATCH 06/12] Removed duplicated line caused by rebase. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36cca4e645..128497cf18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Make `String::from_utf8_unchecked` const. - Implemented `PartialEq` and `Eq` for `Deque`. - Implemented `TyrFrom` for `Deque` from slice. -- Implemented `TryFrom` for `Deque` from slice. ### Changed From 8907839037632d1b36992d618e5afd131ae62ff6 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Thu, 20 Mar 2025 13:01:25 +0000 Subject: [PATCH 07/12] updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e64a511ae8..58afea5fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .#* Cargo.lock target/ +.idea \ No newline at end of file From 5cc1d4b70fc8e72befa654c8844072c86bd8ab6f Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Thu, 20 Mar 2025 13:53:54 +0000 Subject: [PATCH 08/12] Updated Deque coparison. Added at limit test. --- CHANGELOG.md | 2 +- src/deque.rs | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 128497cf18..3360b00a87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `Deque::{swap, swap_unchecked, swap_remove_front, swap_remove_back}`. - Make `String::from_utf8_unchecked` const. - Implemented `PartialEq` and `Eq` for `Deque`. -- Implemented `TyrFrom` for `Deque` from slice. +- Implemented `TryFrom` for `Deque` from slice. ### Changed diff --git a/src/deque.rs b/src/deque.rs index 1e730c7056..831a65d412 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1011,11 +1011,7 @@ impl TryFrom<[T; NS]> for Deque { /// deq2.push_back(3).unwrap(); /// deq2.push_back(4).unwrap(); /// - /// // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. - /// assert_eq!(deq1.len(), deq2.len()); - /// for (i, e1) in deq1.iter().enumerate() { - /// assert_eq!(Some(e1), deq2.get(i)); - /// } + /// assert_eq!(deq1, deq2); /// ``` type Error = (); @@ -1591,8 +1587,13 @@ mod tests { #[test] fn try_from_array() { + // Array is too big error. assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); + // Array is at limit. + assert!(Deque::::try_from([1, 2, 3]).unwrap().is_full()); + + // Array is under limit. let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); let mut deq2 = Deque::::new(); deq2.push_back(1).unwrap(); @@ -1600,10 +1601,6 @@ mod tests { deq2.push_back(3).unwrap(); deq2.push_back(4).unwrap(); - // todo change to `assert_eq!(deq1, deq2);` when PR #521 is merged. - assert_eq!(deq1.len(), deq2.len()); - for (i, e1) in deq1.iter().enumerate() { - assert_eq!(Some(e1), deq2.get(i)); - } + assert_eq!(deq1, deq2); } } From cb9a595ff4fa22ae768d359dce9327ba0758ad4b Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Thu, 20 Mar 2025 13:59:20 +0000 Subject: [PATCH 09/12] Fixed formatting. --- src/deque.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/deque.rs b/src/deque.rs index 831a65d412..422edfba51 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1026,7 +1026,11 @@ impl TryFrom<[T; NS]> for Deque { if size_of::() != 0 { // SAFETY: We already ensured that value fits in deq. unsafe { - ptr::copy_nonoverlapping(value.as_ptr(), deq.buffer.buffer.as_mut_ptr() as *mut T, NS); + ptr::copy_nonoverlapping( + value.as_ptr(), + deq.buffer.buffer.as_mut_ptr() as *mut T, + NS, + ); } } From aca4aa948f61be9efe03d1432418dedadbf043e3 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Tue, 20 May 2025 09:30:05 +0100 Subject: [PATCH 10/12] updated the error type for TryFrom Deque. --- .gitignore | 3 +-- src/deque.rs | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 58afea5fa3..fc026a5f29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ **/*.rs.bk .#* Cargo.lock -target/ -.idea \ No newline at end of file +target/ \ No newline at end of file diff --git a/src/deque.rs b/src/deque.rs index ae1fb02601..b2fd500218 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -39,7 +39,7 @@ use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::{ptr, slice}; - +use crate::CapacityError; use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage}; /// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`]. @@ -1014,11 +1014,11 @@ impl TryFrom<[T; NS]> for Deque { /// /// assert_eq!(deq1, deq2); /// ``` - type Error = (); + type Error = CapacityError; fn try_from(value: [T; NS]) -> Result { if NS > ND { - return Err(()); + return Err(CapacityError); } let mut deq = Self::default(); @@ -1046,7 +1046,7 @@ impl TryFrom<[T; NS]> for Deque { #[cfg(test)] mod tests { use static_assertions::assert_not_impl_any; - + use crate::CapacityError; use super::Deque; // Ensure a `Deque` containing `!Send` values stays `!Send` itself. @@ -1593,7 +1593,7 @@ mod tests { #[test] fn try_from_array() { // Array is too big error. - assert!(Deque::::try_from([1, 2, 3, 4]).is_err()); + assert!(matches!(Deque::::try_from([1, 2, 3, 4]), Err(CapacityError))); // Array is at limit. assert!(Deque::::try_from([1, 2, 3]).unwrap().is_full()); From 2dfeabea32568af31a0eb2f7676cb7cce32b3835 Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Tue, 20 May 2025 09:38:39 +0100 Subject: [PATCH 11/12] Updated the TryFrom Deque example. --- src/deque.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/deque.rs b/src/deque.rs index b2fd500218..2015600c64 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1005,12 +1005,11 @@ impl TryFrom<[T; NS]> for Deque { /// ``` /// use heapless::Deque; /// - /// let deq1 = Deque::::try_from([1, 2, 3, 4]).unwrap(); - /// let mut deq2 = Deque::::new(); + /// let deq1 = Deque::::try_from([1, 2, 3]).unwrap(); + /// let mut deq2 = Deque::::new(); /// deq2.push_back(1).unwrap(); /// deq2.push_back(2).unwrap(); /// deq2.push_back(3).unwrap(); - /// deq2.push_back(4).unwrap(); /// /// assert_eq!(deq1, deq2); /// ``` From 57064152b823786e73944a4f731966573261928b Mon Sep 17 00:00:00 2001 From: William Hicklin Date: Tue, 20 May 2025 09:44:46 +0100 Subject: [PATCH 12/12] Applied clippy and style suggestions. --- src/deque.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/deque.rs b/src/deque.rs index 2015600c64..3f438fd49b 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -33,14 +33,14 @@ //! } //! ``` +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::{ManuallyDrop, MaybeUninit}; use core::{ptr, slice}; -use crate::CapacityError; -use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage}; /// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`]. /// @@ -1028,7 +1028,7 @@ impl TryFrom<[T; NS]> for Deque { unsafe { ptr::copy_nonoverlapping( value.as_ptr(), - deq.buffer.buffer.as_mut_ptr() as *mut T, + deq.buffer.buffer.as_mut_ptr().cast::(), NS, ); } @@ -1044,9 +1044,9 @@ impl TryFrom<[T; NS]> for Deque { #[cfg(test)] mod tests { - use static_assertions::assert_not_impl_any; - use crate::CapacityError; 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); @@ -1592,7 +1592,10 @@ mod tests { #[test] fn try_from_array() { // Array is too big error. - assert!(matches!(Deque::::try_from([1, 2, 3, 4]), Err(CapacityError))); + assert!(matches!( + Deque::::try_from([1, 2, 3, 4]), + Err(CapacityError) + )); // Array is at limit. assert!(Deque::::try_from([1, 2, 3]).unwrap().is_full());