From bbc7b449f84cac248540598f23773cd691003aba Mon Sep 17 00:00:00 2001 From: jonay2000 Date: Thu, 8 Jun 2023 14:00:28 +0200 Subject: [PATCH 1/4] conversions --- src/conversions.rs | 78 ++++++++++++++++++++++ src/lib.rs | 3 + src/with_alloc/alloc_ringbuffer.rs | 56 ++++++++++++++++ src/with_alloc/vecdeque.rs | 103 ++++++++++++++++++++--------- src/with_const_generics.rs | 92 ++++++++++++++++++++++++++ 5 files changed, 299 insertions(+), 33 deletions(-) create mode 100644 src/conversions.rs diff --git a/src/conversions.rs b/src/conversions.rs new file mode 100644 index 0000000..e942878 --- /dev/null +++ b/src/conversions.rs @@ -0,0 +1,78 @@ +extern crate std; + +use crate::RingBufferExt; +use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; +use alloc::collections::{LinkedList, VecDeque}; +use alloc::string::ToString; +use std::vec; + +macro_rules! convert_test { + ($name: ident: $from: expr => $to: ty) => { + #[test] + fn $name() { + let a = $from; + + let b: $to = a.into(); + assert_eq!(b.to_vec(), vec!['1', '2']); + } + }; +} + +macro_rules! convert_tests { + ( + [$($name: ident: $from: expr),* $(,)?] + => $to: ty + ) => { + $( + convert_test!($name: $from => $to); + )* + }; +} + +convert_tests!( + [ + alloc_from_vec: vec!['1', '2'], + alloc_from_ll: {let mut l = LinkedList::new(); l.push_back('1'); l.push_back('2'); l}, + alloc_from_vd: {let mut l = VecDeque::new(); l.push_back('1'); l.push_back('2'); l}, + alloc_from_str: "12".to_string(), + alloc_from_str_slice: "12", + alloc_from_slice: {let a: &[char] = &['1', '2']; a}, + alloc_from_const_slice: {let a: &[char; 2] = &['1', '2']; a}, + alloc_from_arr: {let a: [char; 2] = ['1', '2']; a}, + + alloc_from_cgrb: {let a = ConstGenericRingBuffer::from(['1', '2']); a}, + alloc_from_garb: {let a = GrowableAllocRingBuffer::from(['1', '2']); a}, + ] => AllocRingBuffer::<_, _> +); + +convert_tests!( + [ + growable_alloc_from_vec: vec!['1', '2'], + growable_alloc_from_ll: {let mut l = LinkedList::new(); l.push_back('1'); l.push_back('2'); l}, + growable_alloc_from_vd: {let mut l = VecDeque::new(); l.push_back('1'); l.push_back('2'); l}, + growable_alloc_from_str: "12".to_string(), + growable_alloc_from_str_slice: "12", + growable_alloc_from_slice: {let a: &[char] = &['1', '2']; a}, + growable_alloc_from_const_slice: {let a: &[char; 2] = &['1', '2']; a}, + growable_alloc_from_arr: {let a: [char; 2] = ['1', '2']; a}, + + growable_alloc_from_cgrb: {let a = ConstGenericRingBuffer::from(['1', '2']); a}, + growable_alloc_from_arb: {let a = AllocRingBuffer::from(['1', '2']); a}, + ] => GrowableAllocRingBuffer::<_> +); + +convert_tests!( + [ + const_from_vec: vec!['1', '2'], + const_from_ll: {let mut l = LinkedList::new(); l.push_back('1'); l.push_back('2'); l}, + const_from_vd: {let mut l = VecDeque::new(); l.push_back('1'); l.push_back('2'); l}, + const_from_str: "12".to_string(), + const_from_str_slice: "12", + const_from_slice: {let a: &[char] = &['1', '2']; a}, + const_from_const_slice: {let a: &[char; 2] = &['1', '2']; a}, + const_from_arr: {let a: [char; 2] = ['1', '2']; a}, + + const_from_garb: {let a = GrowableAllocRingBuffer::from(['1', '2']); a}, + const_from_arb: {let a = AllocRingBuffer::from(['1', '2']); a}, + ] => ConstGenericRingBuffer::<_, 2> +); diff --git a/src/lib.rs b/src/lib.rs index 3d83655..e07e0ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,9 @@ pub use with_alloc::alloc_ringbuffer::AllocRingBuffer; #[cfg(feature = "alloc")] pub use with_alloc::vecdeque::GrowableAllocRingBuffer; +#[cfg(test)] +mod conversions; + mod with_const_generics; pub use with_const_generics::ConstGenericRingBuffer; diff --git a/src/with_alloc/alloc_ringbuffer.rs b/src/with_alloc/alloc_ringbuffer.rs index bbe0ef1..3797c29 100644 --- a/src/with_alloc/alloc_ringbuffer.rs +++ b/src/with_alloc/alloc_ringbuffer.rs @@ -123,6 +123,62 @@ impl From<&mut [T]> for AllocRingBuffer { } } +impl From<&mut [T; CAP]> for AllocRingBuffer { + fn from(value: &mut [T; CAP]) -> Self { + Self::from(value.clone()) + } +} + +impl From> for AllocRingBuffer { + fn from(value: alloc::vec::Vec) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.into_iter()); + res + } +} + +impl From> for AllocRingBuffer { + fn from(value: alloc::collections::VecDeque) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.into_iter()); + res + } +} + +impl From> for AllocRingBuffer { + fn from(value: alloc::collections::LinkedList) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.into_iter()); + res + } +} + +impl From for AllocRingBuffer { + fn from(value: alloc::string::String) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.chars()); + res + } +} + +impl From<&str> for AllocRingBuffer { + fn from(value: &str) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.chars()); + res + } +} + +impl From> + for AllocRingBuffer +{ + fn from(mut value: crate::ConstGenericRingBuffer) -> Self { + let mut res = AllocRingBuffer::with_capacity_non_power_of_two(value.len()); + res.extend(value.drain()); + res + } +} + impl Drop for AllocRingBuffer { fn drop(&mut self) { self.drain().for_each(drop); diff --git a/src/with_alloc/vecdeque.rs b/src/with_alloc/vecdeque.rs index b239cab..86b5862 100644 --- a/src/with_alloc/vecdeque.rs +++ b/src/with_alloc/vecdeque.rs @@ -23,6 +23,22 @@ impl From> for GrowableAllocRingBuffer { } } +impl From<&[T; N]> for GrowableAllocRingBuffer { + // the cast here is actually not trivial + #[allow(trivial_casts)] + fn from(value: &[T; N]) -> Self { + Self::from(value as &[T]) + } +} + +impl From<&[T]> for GrowableAllocRingBuffer { + fn from(value: &[T]) -> Self { + let mut rb = Self::new(); + rb.extend(value.iter().cloned()); + rb + } +} + impl From> for GrowableAllocRingBuffer { fn from(mut v: AllocRingBuffer) -> GrowableAllocRingBuffer { let mut rb = GrowableAllocRingBuffer::new(); @@ -31,6 +47,60 @@ impl From> for GrowableAllocRi } } +impl From<&mut [T]> for GrowableAllocRingBuffer { + fn from(value: &mut [T]) -> Self { + Self::from(&*value) + } +} + +impl From<&mut [T; CAP]> for GrowableAllocRingBuffer { + fn from(value: &mut [T; CAP]) -> Self { + Self::from(value.clone()) + } +} + +impl From> for GrowableAllocRingBuffer { + fn from(value: alloc::vec::Vec) -> Self { + let mut res = GrowableAllocRingBuffer::new(); + res.extend(value.into_iter()); + res + } +} + +impl From> for GrowableAllocRingBuffer { + fn from(value: alloc::collections::LinkedList) -> Self { + let mut res = GrowableAllocRingBuffer::new(); + res.extend(value.into_iter()); + res + } +} + +impl From for GrowableAllocRingBuffer { + fn from(value: alloc::string::String) -> Self { + let mut res = GrowableAllocRingBuffer::new(); + res.extend(value.chars()); + res + } +} + +impl From<&str> for GrowableAllocRingBuffer { + fn from(value: &str) -> Self { + let mut res = GrowableAllocRingBuffer::new(); + res.extend(value.chars()); + res + } +} + +impl From> + for GrowableAllocRingBuffer +{ + fn from(mut value: crate::ConstGenericRingBuffer) -> Self { + let mut res = GrowableAllocRingBuffer::new(); + res.extend(value.drain()); + res + } +} + impl Deref for GrowableAllocRingBuffer { type Target = VecDeque; @@ -176,36 +246,3 @@ unsafe impl RingBufferExt for GrowableAllocRingBuffer { unimplemented!() } } - -#[cfg(test)] -mod tests { - use crate::{ - AllocRingBuffer, GrowableAllocRingBuffer, RingBuffer, RingBufferRead, RingBufferWrite, - }; - - #[test] - fn test_convert() { - let mut a = GrowableAllocRingBuffer::new(); - a.push(0); - a.push(1); - - let mut b: AllocRingBuffer<_, _> = a.into(); - assert_eq!(b.capacity(), 2); - assert_eq!(b.len(), 2); - assert_eq!(b.dequeue(), Some(0)); - assert_eq!(b.dequeue(), Some(1)); - } - - #[test] - fn test_convert_back() { - let mut a = AllocRingBuffer::new(2); - a.push(0); - a.push(1); - - let mut b: GrowableAllocRingBuffer<_> = a.into(); - assert_eq!(b.len(), 2); - assert!(b.capacity() >= 2); - assert_eq!(b.dequeue(), Some(0)); - assert_eq!(b.dequeue(), Some(1)); - } -} diff --git a/src/with_const_generics.rs b/src/with_const_generics.rs index 685fee8..f72cc71 100644 --- a/src/with_const_generics.rs +++ b/src/with_const_generics.rs @@ -1,3 +1,4 @@ +use crate::with_alloc::alloc_ringbuffer::RingbufferSize; use crate::{RingBuffer, RingBufferExt, RingBufferRead, RingBufferWrite}; use core::iter::FromIterator; use core::mem; @@ -39,6 +40,97 @@ pub struct ConstGenericRingBuffer { writeptr: usize, } +impl From<[T; CAP]> for ConstGenericRingBuffer { + fn from(value: [T; CAP]) -> Self { + Self { + // Safety: + // T has the same layout as MaybeUninit + // [T; N] has the same layout as [MaybeUninit; N] + buf: unsafe { mem::transmute_copy(&value) }, + readptr: 0, + writeptr: CAP, + } + } +} + +impl From<&[T; CAP]> for ConstGenericRingBuffer { + fn from(value: &[T; CAP]) -> Self { + Self::from(value.clone()) + } +} + +impl From<&[T]> for ConstGenericRingBuffer { + fn from(value: &[T]) -> Self { + value.iter().cloned().collect() + } +} + +impl From<&mut [T; CAP]> for ConstGenericRingBuffer { + fn from(value: &mut [T; CAP]) -> Self { + Self::from(value.clone()) + } +} + +impl From<&mut [T]> for ConstGenericRingBuffer { + fn from(value: &mut [T]) -> Self { + value.iter().cloned().collect() + } +} + +#[cfg(feature = "alloc")] +impl From> for ConstGenericRingBuffer { + fn from(value: alloc::vec::Vec) -> Self { + value.into_iter().collect() + } +} + +#[cfg(feature = "alloc")] +impl From> for ConstGenericRingBuffer { + fn from(value: alloc::collections::VecDeque) -> Self { + value.into_iter().collect() + } +} + +#[cfg(feature = "alloc")] +impl From> + for ConstGenericRingBuffer +{ + fn from(value: alloc::collections::LinkedList) -> Self { + value.into_iter().collect() + } +} + +#[cfg(feature = "alloc")] +impl From for ConstGenericRingBuffer { + fn from(value: alloc::string::String) -> Self { + value.chars().collect() + } +} + +impl From<&str> for ConstGenericRingBuffer { + fn from(value: &str) -> Self { + value.chars().collect() + } +} + +#[cfg(feature = "alloc")] +impl From> + for ConstGenericRingBuffer +{ + fn from(mut value: crate::GrowableAllocRingBuffer) -> Self { + value.drain().collect() + } +} + +#[cfg(feature = "alloc")] +impl From> + for ConstGenericRingBuffer +{ + fn from(mut value: crate::AllocRingBuffer) -> Self { + value.drain().collect() + } +} + impl Drop for ConstGenericRingBuffer { fn drop(&mut self) { self.drain().for_each(drop); From a486d55740d3d30671c0402cb4493cd6a054e3a0 Mon Sep 17 00:00:00 2001 From: jonay2000 Date: Thu, 8 Jun 2023 14:13:24 +0200 Subject: [PATCH 2/4] more coverage --- src/conversions.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/conversions.rs b/src/conversions.rs index e942878..9863b6a 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -4,6 +4,7 @@ use crate::RingBufferExt; use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; use alloc::collections::{LinkedList, VecDeque}; use alloc::string::ToString; +use core::ops::Deref; use std::vec; macro_rules! convert_test { @@ -76,3 +77,42 @@ convert_tests!( const_from_arb: {let a = AllocRingBuffer::from(['1', '2']); a}, ] => ConstGenericRingBuffer::<_, 2> ); + +#[test] +fn test_extra_conversions_growable() { + let a: &mut [i32; 2] = &mut [1, 2]; + let a = GrowableAllocRingBuffer::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); + + let a: &mut [i32] = &mut [1, 2]; + let a = GrowableAllocRingBuffer::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); + + let mut b = VecDeque::::new(); + b.push_back(1); + b.push_back(2); + assert_eq!(a.deref(), &b); + assert_eq!(a.as_ref(), &b); +} + +#[test] +fn test_extra_conversions_alloc() { + let a: &mut [i32; 2] = &mut [1, 2]; + let a = AllocRingBuffer::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); + + let a: &mut [i32] = &mut [1, 2]; + let a = AllocRingBuffer::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); +} + +#[test] +fn test_extra_conversions_const() { + let a: &mut [i32; 2] = &mut [1, 2]; + let a = ConstGenericRingBuffer::<_, 2>::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); + + let a: &mut [i32] = &mut [1, 2]; + let a = ConstGenericRingBuffer::<_, 2>::from(a); + assert_eq!(a.to_vec(), vec![1, 2]); +} From 07bcb13513f6e7258a8dfe0cf52c9f279548caa0 Mon Sep 17 00:00:00 2001 From: jonay2000 Date: Thu, 8 Jun 2023 14:18:12 +0200 Subject: [PATCH 3/4] fix some coverage stuff --- src/conversions.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/conversions.rs b/src/conversions.rs index 9863b6a..e1346fe 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -1,7 +1,7 @@ extern crate std; -use crate::RingBufferExt; use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; +use crate::{RingBufferExt, RingBufferWrite}; use alloc::collections::{LinkedList, VecDeque}; use alloc::string::ToString; use core::ops::Deref; @@ -13,8 +13,10 @@ macro_rules! convert_test { fn $name() { let a = $from; - let b: $to = a.into(); + let mut b: $to = a.into(); assert_eq!(b.to_vec(), vec!['1', '2']); + b.push('3'); + assert_eq!(b, b); } }; } From ce9c236f69dc84743417bcecf9ad80590358b7a5 Mon Sep 17 00:00:00 2001 From: jonay2000 Date: Thu, 8 Jun 2023 14:26:52 +0200 Subject: [PATCH 4/4] move conversions --- src/lib.rs | 3 --- tests/compiletests.rs | 3 +++ {src => tests}/conversions.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename {src => tests}/conversions.rs (96%) diff --git a/src/lib.rs b/src/lib.rs index e07e0ba..3d83655 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,9 +79,6 @@ pub use with_alloc::alloc_ringbuffer::AllocRingBuffer; #[cfg(feature = "alloc")] pub use with_alloc::vecdeque::GrowableAllocRingBuffer; -#[cfg(test)] -mod conversions; - mod with_const_generics; pub use with_const_generics::ConstGenericRingBuffer; diff --git a/tests/compiletests.rs b/tests/compiletests.rs index 4fa9e1d..8c3a2a2 100644 --- a/tests/compiletests.rs +++ b/tests/compiletests.rs @@ -2,6 +2,9 @@ extern crate compiletest_rs as compiletest; use std::path::PathBuf; +#[cfg(test)] +mod conversions; + fn run_mode(mode: &'static str) { let mut config = compiletest::Config::default(); diff --git a/src/conversions.rs b/tests/conversions.rs similarity index 96% rename from src/conversions.rs rename to tests/conversions.rs index e1346fe..8140f40 100644 --- a/src/conversions.rs +++ b/tests/conversions.rs @@ -1,10 +1,10 @@ -extern crate std; +extern crate alloc; -use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; -use crate::{RingBufferExt, RingBufferWrite}; use alloc::collections::{LinkedList, VecDeque}; use alloc::string::ToString; use core::ops::Deref; +use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; +use ringbuffer::{RingBufferExt, RingBufferWrite}; use std::vec; macro_rules! convert_test {