From 377d110b478a16225a094893ad02934a85851dcc Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 14:41:37 +0100 Subject: [PATCH 01/11] Add basic iterator --- wrapped_slab/src/lib.rs | 6 ++++++ wrapped_slab/tests/basic.rs | 33 ++++++++++++++++++++++++++++----- wrapped_slab_derive/src/lib.rs | 8 ++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/wrapped_slab/src/lib.rs b/wrapped_slab/src/lib.rs index 44d0bbf..1064eec 100644 --- a/wrapped_slab/src/lib.rs +++ b/wrapped_slab/src/lib.rs @@ -1,4 +1,10 @@ pub use wrapped_slab_derive::WrappedSlab; +#[derive(Clone)] +pub enum Entry { + Vacant(usize), + Occupied(T), +} + #[doc(hidden)] pub use slab; diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index efbc12f..80704c2 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -1,6 +1,6 @@ use wrapped_slab::WrappedSlab; -#[derive(WrappedSlab)] +#[derive(WrappedSlab, PartialEq, Debug)] struct TestUnitStruct(String); #[test] @@ -23,10 +23,16 @@ fn test_unit_struct() { let next_key: TestUnitStructKey = next_entry.key(); let next_entry_ref: &mut TestUnitStruct = next_entry.insert(TestUnitStruct(format!("{next_key:?}"))); - assert_eq!(next_entry_ref.0, format!("{next_key:?}")) + assert_eq!(next_entry_ref.0, format!("{next_key:?}")); + + let mut iter = slab.iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, 0); + assert_eq!(s, &TestUnitStruct("TestUnitStructKey(0)".to_string())); + assert_eq!(iter.next(), None); } -#[derive(WrappedSlab)] +#[derive(WrappedSlab, PartialEq, Debug)] struct TestStruct { field1: String, } @@ -54,7 +60,18 @@ fn test_struct() { let next_entry_ref: &mut TestStruct = next_entry.insert(TestStruct { field1: format!("{next_key:?}"), }); - assert_eq!(next_entry_ref.field1, format!("{next_key:?}")) + assert_eq!(next_entry_ref.field1, format!("{next_key:?}")); + + let mut iter = slab.iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, 0); + assert_eq!( + s, + &TestStruct { + field1: "TestStructKey(0)".to_string() + } + ); + assert_eq!(iter.next(), None); } #[derive(WrappedSlab, PartialEq, Debug)] @@ -85,5 +102,11 @@ fn test_enum() { assert_eq!( next_entry_ref, &mut TestEnum::VariantOne(format!("{next_key:?}")) - ) + ); + + let mut iter = slab.iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, 0); + assert_eq!(s, &TestEnum::VariantOne("TestEnumKey(0)".to_string())); + assert_eq!(iter.next(), None); } diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 41e7e34..6ef373e 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -123,6 +123,14 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS pub fn contains(&self, key: #key_name) -> bool { self.0.contains(key.0) } + + pub fn iter(&self) -> wrapped_slab::slab::Iter<'_, #element_name> { + self.0.iter() + } + + pub fn iter_mut(&mut self) -> wrapped_slab::slab::IterMut<'_, #element_name> { + self.0.iter_mut() + } } }; From eaadf94c3fed62b97974051540420186aa262ac1 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:05:59 +0100 Subject: [PATCH 02/11] wrap iterator so index is key --- wrapped_slab/tests/basic.rs | 39 ++++++++++++++++++++++++++++------ wrapped_slab_derive/src/lib.rs | 38 +++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index 80704c2..cd6e21f 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -25,10 +25,17 @@ fn test_unit_struct() { next_entry.insert(TestUnitStruct(format!("{next_key:?}"))); assert_eq!(next_entry_ref.0, format!("{next_key:?}")); + let mut iter = slab.iter_mut(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestUnitStructKey(0)); + assert_eq!(s, &mut TestUnitStruct("TestUnitStructKey(0)".to_string())); + s.0 = "modified".to_string(); + assert_eq!(iter.next(), None); + let mut iter = slab.iter(); let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, 0); - assert_eq!(s, &TestUnitStruct("TestUnitStructKey(0)".to_string())); + assert_eq!(idx, TestUnitStructKey(0)); + assert_eq!(s, &TestUnitStruct("modified".to_string())); assert_eq!(iter.next(), None); } @@ -62,13 +69,25 @@ fn test_struct() { }); assert_eq!(next_entry_ref.field1, format!("{next_key:?}")); + let mut iter = slab.iter_mut(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestStructKey(0)); + assert_eq!( + s, + &mut TestStruct { + field1: "TestStructKey(0)".to_string() + } + ); + s.field1 = "modified".to_string(); + assert_eq!(iter.next(), None); + let mut iter = slab.iter(); let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, 0); + assert_eq!(idx, TestStructKey(0)); assert_eq!( s, &TestStruct { - field1: "TestStructKey(0)".to_string() + field1: "modified".to_string() } ); assert_eq!(iter.next(), None); @@ -77,6 +96,7 @@ fn test_struct() { #[derive(WrappedSlab, PartialEq, Debug)] enum TestEnum { VariantOne(String), + VariantTwo, } #[test] @@ -104,9 +124,16 @@ fn test_enum() { &mut TestEnum::VariantOne(format!("{next_key:?}")) ); + let mut iter = slab.iter_mut(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestEnumKey(0)); + assert_eq!(s, &mut TestEnum::VariantOne("TestEnumKey(0)".to_string())); + *s = TestEnum::VariantTwo; + assert_eq!(iter.next(), None); + let mut iter = slab.iter(); let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, 0); - assert_eq!(s, &TestEnum::VariantOne("TestEnumKey(0)".to_string())); + assert_eq!(idx, TestEnumKey(0)); + assert_eq!(s, &TestEnum::VariantTwo); assert_eq!(iter.next(), None); } diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 6ef373e..fed96ac 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -15,6 +15,8 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS let slab_name = format_ident!("{element_name}Slab"); let vacant_entry_name = format_ident!("{element_name}VacantEntry"); let key_name = format_ident!("{element_name}Key"); + let iter_name = format_ident!("{element_name}Iter"); + let iter_mut_name = format_ident!("{element_name}IterMut"); let expanded = quote! { #[derive(Default)] @@ -35,6 +37,34 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + struct #iter_name<'a>(wrapped_slab::slab::Iter<'a, #element_name>); + + impl<'a> Iterator for #iter_name<'a> { + type Item = (#key_name, &'a #element_name); + + fn next(&mut self) -> Option { + self.0.next().map(|(key, val)| (#key_name(key), val)) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + + struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); + + impl<'a> Iterator for #iter_mut_name<'a> { + type Item = (#key_name, &'a mut #element_name); + + fn next(&mut self) -> Option { + self.0.next().map(|(key, val)| (#key_name(key), val)) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + impl #slab_name { pub const fn new() -> Self { Self(wrapped_slab::slab::Slab::new()) @@ -124,12 +154,12 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS self.0.contains(key.0) } - pub fn iter(&self) -> wrapped_slab::slab::Iter<'_, #element_name> { - self.0.iter() + pub fn iter(&self) -> #iter_name<'_> { + #iter_name(self.0.iter()) } - pub fn iter_mut(&mut self) -> wrapped_slab::slab::IterMut<'_, #element_name> { - self.0.iter_mut() + pub fn iter_mut(&mut self) -> #iter_mut_name<'_> { + #iter_mut_name(self.0.iter_mut()) } } }; From 7f5bdb380f648359fd9eb0fe09c7d7b52e8d199c Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:09:32 +0100 Subject: [PATCH 03/11] add into_iter;2A --- wrapped_slab/tests/basic.rs | 23 +++++++++++++++++++++++ wrapped_slab_derive/src/lib.rs | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index cd6e21f..f1f3dc5 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -37,6 +37,12 @@ fn test_unit_struct() { assert_eq!(idx, TestUnitStructKey(0)); assert_eq!(s, &TestUnitStruct("modified".to_string())); assert_eq!(iter.next(), None); + + let mut iter = slab.into_iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestUnitStructKey(0)); + assert_eq!(s, TestUnitStruct("modified".to_string())); + assert_eq!(iter.next(), None); } #[derive(WrappedSlab, PartialEq, Debug)] @@ -91,6 +97,17 @@ fn test_struct() { } ); assert_eq!(iter.next(), None); + + let mut iter = slab.into_iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestStructKey(0)); + assert_eq!( + s, + TestStruct { + field1: "modified".to_string() + } + ); + assert_eq!(iter.next(), None); } #[derive(WrappedSlab, PartialEq, Debug)] @@ -136,4 +153,10 @@ fn test_enum() { assert_eq!(idx, TestEnumKey(0)); assert_eq!(s, &TestEnum::VariantTwo); assert_eq!(iter.next(), None); + + let mut iter = slab.into_iter(); + let (idx, s) = iter.next().unwrap(); + assert_eq!(idx, TestEnumKey(0)); + assert_eq!(s, TestEnum::VariantTwo); + assert_eq!(iter.next(), None); } diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index fed96ac..ab13f02 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -17,6 +17,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS let key_name = format_ident!("{element_name}Key"); let iter_name = format_ident!("{element_name}Iter"); let iter_mut_name = format_ident!("{element_name}IterMut"); + let into_iter_name = format_ident!("{element_name}IntoIter"); let expanded = quote! { #[derive(Default)] @@ -65,6 +66,20 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); + + impl Iterator for #into_iter_name { + type Item = (#key_name, #element_name); + + fn next(&mut self) -> Option { + self.0.next().map(|(key, val)| (#key_name(key), val)) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + impl #slab_name { pub const fn new() -> Self { Self(wrapped_slab::slab::Slab::new()) @@ -161,6 +176,10 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS pub fn iter_mut(&mut self) -> #iter_mut_name<'_> { #iter_mut_name(self.0.iter_mut()) } + + pub fn into_iter(self) -> #into_iter_name { + #into_iter_name(self.0.into_iter()) + } } }; From 266bc7777384717bef4ff262e423506ae7b09d1f Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:18:02 +0100 Subject: [PATCH 04/11] Add IntoIterator trait --- wrapped_slab_derive/src/lib.rs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index ab13f02..3c5ff3c 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -38,6 +38,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + #[derive(Debug)] struct #iter_name<'a>(wrapped_slab::slab::Iter<'a, #element_name>); impl<'a> Iterator for #iter_name<'a> { @@ -52,6 +53,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + #[derive(Debug)] struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); impl<'a> Iterator for #iter_mut_name<'a> { @@ -66,6 +68,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + #[derive(Debug)] struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); impl Iterator for #into_iter_name { @@ -80,6 +83,33 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl IntoIterator for #slab_name { + type Item = (#key_name, #element_name); + type IntoIter = #into_iter_name; + + fn into_iter(self) -> Self::IntoIter { + #into_iter_name(self.0.into_iter()) + } + } + + impl<'a> IntoIterator for &'a #slab_name { + type Item = (#key_name, &'a #element_name); + type IntoIter = #iter_name<'a>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } + } + + impl<'a> IntoIterator for &'a mut #slab_name { + type Item = (#key_name, &'a mut #element_name); + type IntoIter = #iter_mut_name<'a>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } + } + impl #slab_name { pub const fn new() -> Self { Self(wrapped_slab::slab::Slab::new()) @@ -176,10 +206,6 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS pub fn iter_mut(&mut self) -> #iter_mut_name<'_> { #iter_mut_name(self.0.iter_mut()) } - - pub fn into_iter(self) -> #into_iter_name { - #into_iter_name(self.0.into_iter()) - } } }; From bbadb8c68a1cad09e8011892232d2a9f95048f90 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:19:50 +0100 Subject: [PATCH 05/11] set vis on iterators --- wrapped_slab_derive/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 3c5ff3c..6f9fcd0 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -39,7 +39,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } #[derive(Debug)] - struct #iter_name<'a>(wrapped_slab::slab::Iter<'a, #element_name>); + #element_vis struct #iter_name<'a>(wrapped_slab::slab::Iter<'a, #element_name>); impl<'a> Iterator for #iter_name<'a> { type Item = (#key_name, &'a #element_name); @@ -54,7 +54,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } #[derive(Debug)] - struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); + #element_vis struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); impl<'a> Iterator for #iter_mut_name<'a> { type Item = (#key_name, &'a mut #element_name); @@ -69,7 +69,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } #[derive(Debug)] - struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); + #element_vis struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); impl Iterator for #into_iter_name { type Item = (#key_name, #element_name); From 1a564feda60ad9c8689bfa244a92367689052990 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:38:30 +0100 Subject: [PATCH 06/11] add drain --- wrapped_slab/tests/basic.rs | 18 ++++++++++++++++++ wrapped_slab_derive/src/lib.rs | 34 +++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index f1f3dc5..92fb40e 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -160,3 +160,21 @@ fn test_enum() { assert_eq!(s, TestEnum::VariantTwo); assert_eq!(iter.next(), None); } + +#[test] +fn test_drain() { + let mut slab = TestEnumSlab::with_capacity(32); + slab.reserve(64); + assert_eq!(slab.capacity(), 64); + + slab.insert(TestEnum::VariantTwo); + + let mut drain = slab.drain(); + assert_eq!(drain.len(), 1); + let s = drain.next().unwrap(); + assert_eq!(s, TestEnum::VariantTwo); + assert_eq!(drain.len(), 0); + drop(drain); + + assert_eq!(slab.len(), 0); +} diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 6f9fcd0..056c950 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -41,6 +41,12 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS #[derive(Debug)] #element_vis struct #iter_name<'a>(wrapped_slab::slab::Iter<'a, #element_name>); + #[derive(Debug)] + #element_vis struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); + + #[derive(Debug)] + #element_vis struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); + impl<'a> Iterator for #iter_name<'a> { type Item = (#key_name, &'a #element_name); @@ -53,9 +59,6 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } - #[derive(Debug)] - #element_vis struct #iter_mut_name<'a>(wrapped_slab::slab::IterMut<'a, #element_name>); - impl<'a> Iterator for #iter_mut_name<'a> { type Item = (#key_name, &'a mut #element_name); @@ -68,9 +71,6 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } - #[derive(Debug)] - #element_vis struct #into_iter_name(wrapped_slab::slab::IntoIter<#element_name>); - impl Iterator for #into_iter_name { type Item = (#key_name, #element_name); @@ -83,15 +83,6 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } - impl IntoIterator for #slab_name { - type Item = (#key_name, #element_name); - type IntoIter = #into_iter_name; - - fn into_iter(self) -> Self::IntoIter { - #into_iter_name(self.0.into_iter()) - } - } - impl<'a> IntoIterator for &'a #slab_name { type Item = (#key_name, &'a #element_name); type IntoIter = #iter_name<'a>; @@ -110,6 +101,15 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl IntoIterator for #slab_name { + type Item = (#key_name, #element_name); + type IntoIter = #into_iter_name; + + fn into_iter(self) -> Self::IntoIter { + #into_iter_name(self.0.into_iter()) + } + } + impl #slab_name { pub const fn new() -> Self { Self(wrapped_slab::slab::Slab::new()) @@ -206,6 +206,10 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS pub fn iter_mut(&mut self) -> #iter_mut_name<'_> { #iter_mut_name(self.0.iter_mut()) } + + pub fn drain(&mut self) -> wrapped_slab::slab::Drain<'_, #element_name> { + self.0.drain() + } } }; From bcac40d57d889893806cefb0ac8aaddb96d13391 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:42:32 +0100 Subject: [PATCH 07/11] impl index --- wrapped_slab/tests/basic.rs | 15 +++++++++++++++ wrapped_slab_derive/src/lib.rs | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index 92fb40e..5f9a5db 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -178,3 +178,18 @@ fn test_drain() { assert_eq!(slab.len(), 0); } + +#[test] +fn test_index() { + let mut slab = TestEnumSlab::with_capacity(32); + slab.reserve(64); + assert_eq!(slab.capacity(), 64); + + slab.insert(TestEnum::VariantTwo); + + let s = &slab[TestEnumKey(0)]; + assert_eq!(s, &TestEnum::VariantTwo); + + let s = &mut slab[TestEnumKey(0)]; + assert_eq!(s, &mut TestEnum::VariantTwo); +} diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 056c950..1f12e25 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -110,6 +110,20 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl std::ops::Index<#key_name> for #slab_name { + type Output = #element_name; + + fn index(&self, key: #key_name) -> &#element_name { + self.0.index(key.0) + } + } + + impl std::ops::IndexMut<#key_name> for #slab_name { + fn index_mut(&mut self, key: #key_name) -> &mut #element_name { + self.0.index_mut(key.0) + } + } + impl #slab_name { pub const fn new() -> Self { Self(wrapped_slab::slab::Slab::new()) From ab4c35988e41228eb249658e3db065ac067afe95 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:45:38 +0100 Subject: [PATCH 08/11] clean up tests --- wrapped_slab/tests/basic.rs | 80 ++++++------------------------------- 1 file changed, 13 insertions(+), 67 deletions(-) diff --git a/wrapped_slab/tests/basic.rs b/wrapped_slab/tests/basic.rs index 5f9a5db..c71768c 100644 --- a/wrapped_slab/tests/basic.rs +++ b/wrapped_slab/tests/basic.rs @@ -18,31 +18,6 @@ fn test_unit_struct() { assert_eq!(val.0, "testing"); assert_eq!(slab.len(), 0); - - let next_entry: TestUnitStructVacantEntry = slab.vacant_entry(); - let next_key: TestUnitStructKey = next_entry.key(); - let next_entry_ref: &mut TestUnitStruct = - next_entry.insert(TestUnitStruct(format!("{next_key:?}"))); - assert_eq!(next_entry_ref.0, format!("{next_key:?}")); - - let mut iter = slab.iter_mut(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestUnitStructKey(0)); - assert_eq!(s, &mut TestUnitStruct("TestUnitStructKey(0)".to_string())); - s.0 = "modified".to_string(); - assert_eq!(iter.next(), None); - - let mut iter = slab.iter(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestUnitStructKey(0)); - assert_eq!(s, &TestUnitStruct("modified".to_string())); - assert_eq!(iter.next(), None); - - let mut iter = slab.into_iter(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestUnitStructKey(0)); - assert_eq!(s, TestUnitStruct("modified".to_string())); - assert_eq!(iter.next(), None); } #[derive(WrappedSlab, PartialEq, Debug)] @@ -67,47 +42,6 @@ fn test_struct() { assert_eq!(val.field1, "testing"); assert_eq!(slab.len(), 0); - - let next_entry: TestStructVacantEntry = slab.vacant_entry(); - let next_key: TestStructKey = next_entry.key(); - let next_entry_ref: &mut TestStruct = next_entry.insert(TestStruct { - field1: format!("{next_key:?}"), - }); - assert_eq!(next_entry_ref.field1, format!("{next_key:?}")); - - let mut iter = slab.iter_mut(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestStructKey(0)); - assert_eq!( - s, - &mut TestStruct { - field1: "TestStructKey(0)".to_string() - } - ); - s.field1 = "modified".to_string(); - assert_eq!(iter.next(), None); - - let mut iter = slab.iter(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestStructKey(0)); - assert_eq!( - s, - &TestStruct { - field1: "modified".to_string() - } - ); - assert_eq!(iter.next(), None); - - let mut iter = slab.into_iter(); - let (idx, s) = iter.next().unwrap(); - assert_eq!(idx, TestStructKey(0)); - assert_eq!( - s, - TestStruct { - field1: "modified".to_string() - } - ); - assert_eq!(iter.next(), None); } #[derive(WrappedSlab, PartialEq, Debug)] @@ -131,6 +65,12 @@ fn test_enum() { assert_eq!(val, TestEnum::VariantOne("testing".into())); assert_eq!(slab.len(), 0); +} + +#[test] +fn test_vacant_entry() { + let mut slab = TestEnumSlab::default(); + slab.insert(TestEnum::VariantOne("testing".into())); let next_entry: TestEnumVacantEntry = slab.vacant_entry(); let next_key: TestEnumKey = next_entry.key(); @@ -140,11 +80,17 @@ fn test_enum() { next_entry_ref, &mut TestEnum::VariantOne(format!("{next_key:?}")) ); +} + +#[test] +fn test_iter() { + let mut slab = TestEnumSlab::default(); + slab.insert(TestEnum::VariantOne("testing".into())); let mut iter = slab.iter_mut(); let (idx, s) = iter.next().unwrap(); assert_eq!(idx, TestEnumKey(0)); - assert_eq!(s, &mut TestEnum::VariantOne("TestEnumKey(0)".to_string())); + assert_eq!(s, &mut TestEnum::VariantOne("testing".to_string())); *s = TestEnum::VariantTwo; assert_eq!(iter.next(), None); From 03fac40f461be0eb514b293208ee42e0725ef63a Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:51:46 +0100 Subject: [PATCH 09/11] impl double ended, exact size, and fused iter --- wrapped_slab_derive/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/wrapped_slab_derive/src/lib.rs b/wrapped_slab_derive/src/lib.rs index 1f12e25..06f47d6 100644 --- a/wrapped_slab_derive/src/lib.rs +++ b/wrapped_slab_derive/src/lib.rs @@ -23,6 +23,7 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS #[derive(Default)] #element_vis struct #slab_name(wrapped_slab::slab::Slab<#element_name>); + #[derive(Debug)] #element_vis struct #vacant_entry_name<'a>(wrapped_slab::slab::VacantEntry<'a, #element_name>); #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] @@ -59,6 +60,20 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl DoubleEndedIterator for #iter_name<'_> { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(key, val)| (#key_name(key), val)) + } + } + + impl ExactSizeIterator for #iter_name<'_> { + fn len(&self) -> usize { + self.0.len() + } + } + + impl core::iter::FusedIterator for #iter_name<'_> {} + impl<'a> Iterator for #iter_mut_name<'a> { type Item = (#key_name, &'a mut #element_name); @@ -71,6 +86,20 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl DoubleEndedIterator for #iter_mut_name<'_> { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(key, val)| (#key_name(key), val)) + } + } + + impl ExactSizeIterator for #iter_mut_name<'_> { + fn len(&self) -> usize { + self.0.len() + } + } + + impl core::iter::FusedIterator for #iter_mut_name<'_> {} + impl Iterator for #into_iter_name { type Item = (#key_name, #element_name); @@ -83,6 +112,20 @@ pub fn wrapped_slab_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS } } + impl DoubleEndedIterator for #into_iter_name { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(key, val)| (#key_name(key), val)) + } + } + + impl ExactSizeIterator for #into_iter_name { + fn len(&self) -> usize { + self.0.len() + } + } + + impl core::iter::FusedIterator for #into_iter_name {} + impl<'a> IntoIterator for &'a #slab_name { type Item = (#key_name, &'a #element_name); type IntoIter = #iter_name<'a>; From 012e13c8a5c693cc3b1489aceb898035ef0e46e8 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:55:20 +0100 Subject: [PATCH 10/11] update readme and releases --- README.md | 6 +----- RELEASES.md | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9cac869..cf4bc8c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [Also available on crates.io.](https://crates.io/crates/wrapped_slab) -Very simple Rust library useful when you want stronger type guarantees than Slab's `usize` keys. Generates `TSlab(Slab)` that accepts `TKey` instead of `usize`. `TVacantEntry(VacantEntry)` is also generated along the same lines. +Very simple Rust library useful when you want stronger type guarantees than Slab's `usize` keys. Generates `TSlab(Slab)` that accepts `TKey` instead of `usize`. `TVacantEntry(VacantEntry)` is also generated along the same lines. This should be a drop-in replacement for `Slab`, provided all the keys are changed from `usize` to `TKey`. ## Example @@ -23,7 +23,3 @@ fn main() { // See wrapped_slab/tests/ for more examples } ``` - -## Warning - -This is a very early version, however the aim is to just translate the Slab API 1-1. Currently the only things missing are Iter, IterMut, drain, and retain. diff --git a/RELEASES.md b/RELEASES.md index 01f5aa7..40bd970 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,8 @@ +Version 0.2.0 (2023-07-24) +========================== + +- Implement Iter, IterMut, and Drain. + Version 0.1.1 (2023-07-19) ========================== From 4d75bfdaa0a8888cd13e20552e6327dfce71feb9 Mon Sep 17 00:00:00 2001 From: Louis Wyborn Date: Mon, 24 Jul 2023 15:57:50 +0100 Subject: [PATCH 11/11] bump version --- wrapped_slab/Cargo.toml | 6 +++--- wrapped_slab_derive/Cargo.toml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wrapped_slab/Cargo.toml b/wrapped_slab/Cargo.toml index 57f6e82..e805e76 100644 --- a/wrapped_slab/Cargo.toml +++ b/wrapped_slab/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wrapped_slab" -version = "0.1.1" +version = "0.2.0" edition = "2021" authors = ["Louis Wyborn "] rust-version = "1.62" @@ -14,7 +14,7 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -wrapped_slab_derive = {version="0.1.0", path="../wrapped_slab_derive"} +wrapped_slab_derive = { version = "0.2.0", path = "../wrapped_slab_derive" } # Used as the backing store of all the elements. -slab = { version = "0.4" } \ No newline at end of file +slab = { version = "0.4" } diff --git a/wrapped_slab_derive/Cargo.toml b/wrapped_slab_derive/Cargo.toml index be61d7f..ea2170e 100644 --- a/wrapped_slab_derive/Cargo.toml +++ b/wrapped_slab_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wrapped_slab_derive" -version = "0.1.1" +version = "0.2.0" edition = "2021" authors = ["Louis Wyborn "] rust-version = "1.62" @@ -21,10 +21,10 @@ syn = { version = "1.0", features = ["full"] } quote = { version = "1.0" } # Necessary for syn and quote -proc-macro2 = { version = "1.0"} +proc-macro2 = { version = "1.0" } # Better error handling in proc macros, avoids using panic! proc-macro-error = { version = "1.0" } [lib] -proc-macro = true \ No newline at end of file +proc-macro = true