diff --git a/module/core/reflect_tools/src/reflect/fields.rs b/module/core/reflect_tools/src/reflect/fields.rs index 428c95237b..edbdfbc9b4 100644 --- a/module/core/reflect_tools/src/reflect/fields.rs +++ b/module/core/reflect_tools/src/reflect/fields.rs @@ -112,6 +112,10 @@ mod private mod vec; mod hmap; mod bmap; +mod hset; +mod bset; +mod deque; +mod llist; #[ doc( inline ) ] #[ allow( unused_imports ) ] diff --git a/module/core/reflect_tools/src/reflect/fields/bset.rs b/module/core/reflect_tools/src/reflect/fields/bset.rs new file mode 100644 index 0000000000..e68d4d7e4b --- /dev/null +++ b/module/core/reflect_tools/src/reflect/fields/bset.rs @@ -0,0 +1,65 @@ +//! +//! Implement fields for BTreeSet. +//! + +use crate::*; +use std::borrow::Cow; +use collection_tools::BTreeSet; + +impl< V, Borrowed > Fields< usize, &'_ Borrowed > for BTreeSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = &'v Borrowed + where Self : 'v, V : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, val.borrow() ) ) + } + +} + +impl< V, Borrowed > Fields< usize, Option< Cow< '_, Borrowed > > > for BTreeSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = Option< Cow< 'v, Borrowed > > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, Some( Cow::Borrowed( val.borrow() ) ) ) ) + } + +} + +impl< V, Borrowed, Marker > Fields< usize, OptionalCow< '_, Borrowed, Marker > > for BTreeSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, + Marker : Clone + Copy + 'static, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = OptionalCow< 'v, Borrowed, Marker > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, OptionalCow::from( val.borrow() ) ) ) + } + +} diff --git a/module/core/reflect_tools/src/reflect/fields/deque.rs b/module/core/reflect_tools/src/reflect/fields/deque.rs new file mode 100644 index 0000000000..734255ad1a --- /dev/null +++ b/module/core/reflect_tools/src/reflect/fields/deque.rs @@ -0,0 +1,65 @@ +//! +//! Implement fields for Deque. +//! + +use crate::*; +use std::borrow::Cow; +use collection_tools::VecDeque; + +impl< V, Borrowed > Fields< usize, &'_ Borrowed > for VecDeque< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = &'v Borrowed + where Self : 'v, V : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, val.borrow() ) ) + } + +} + +impl< V, Borrowed > Fields< usize, Option< Cow< '_, Borrowed > > > for VecDeque< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = Option< Cow< 'v, Borrowed > > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, Some( Cow::Borrowed( val.borrow() ) ) ) ) + } + +} + +impl< V, Borrowed, Marker > Fields< usize, OptionalCow< '_, Borrowed, Marker > > for VecDeque< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, + Marker : Clone + Copy + 'static, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = OptionalCow< 'v, Borrowed, Marker > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, OptionalCow::from( val.borrow() ) ) ) + } + +} diff --git a/module/core/reflect_tools/src/reflect/fields/hset.rs b/module/core/reflect_tools/src/reflect/fields/hset.rs new file mode 100644 index 0000000000..cfc01be06e --- /dev/null +++ b/module/core/reflect_tools/src/reflect/fields/hset.rs @@ -0,0 +1,65 @@ +//! +//! Implement fields for HashSet. +//! + +use crate::*; +use std::borrow::Cow; +use std::collections::HashSet; + +impl< V, Borrowed > Fields< usize, &'_ Borrowed > for HashSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = &'v Borrowed + where Self : 'v, V : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, val.borrow() ) ) + } + +} + +impl< V, Borrowed > Fields< usize, Option< Cow< '_, Borrowed > > > for HashSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = Option< Cow< 'v, Borrowed > > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, Some( Cow::Borrowed( val.borrow() ) ) ) ) + } + +} + +impl< V, Borrowed, Marker > Fields< usize, OptionalCow< '_, Borrowed, Marker > > for HashSet< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, + Marker : Clone + Copy + 'static, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = OptionalCow< 'v, Borrowed, Marker > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, OptionalCow::from( val.borrow() ) ) ) + } + +} diff --git a/module/core/reflect_tools/src/reflect/fields/llist.rs b/module/core/reflect_tools/src/reflect/fields/llist.rs new file mode 100644 index 0000000000..40ca1ced98 --- /dev/null +++ b/module/core/reflect_tools/src/reflect/fields/llist.rs @@ -0,0 +1,65 @@ +//! +//! Implement fields for LinkedList. +//! + +use crate::*; +use std::borrow::Cow; +use collection_tools::LinkedList; + +impl< V, Borrowed > Fields< usize, &'_ Borrowed > for LinkedList< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = &'v Borrowed + where Self : 'v, V : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, val.borrow() ) ) + } + +} + +impl< V, Borrowed > Fields< usize, Option< Cow< '_, Borrowed > > > for LinkedList< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = Option< Cow< 'v, Borrowed > > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, Some( Cow::Borrowed( val.borrow() ) ) ) ) + } + +} + +impl< V, Borrowed, Marker > Fields< usize, OptionalCow< '_, Borrowed, Marker > > for LinkedList< V > +where + Borrowed : std::borrow::ToOwned + 'static + ?Sized, + V : std::borrow::Borrow< Borrowed >, + Marker : Clone + Copy + 'static, +{ + + type Key< 'k > = usize + where Self : 'k, usize : 'k; + + type Val< 'v > = OptionalCow< 'v, Borrowed, Marker > + where Self : 'v; + + fn fields< 's >( &'s self ) -> impl IteratorTrait< Item = ( Self::Key< 's >, Self::Val< 's > ) > + { + self.iter().enumerate().map( move | ( key, val ) | ( key, OptionalCow::from( val.borrow() ) ) ) + } + +} diff --git a/module/core/reflect_tools/tests/inc/fundamental/fields_bset.rs b/module/core/reflect_tools/tests/inc/fundamental/fields_bset.rs new file mode 100644 index 0000000000..5a811ad569 --- /dev/null +++ b/module/core/reflect_tools/tests/inc/fundamental/fields_bset.rs @@ -0,0 +1,61 @@ +#[ allow( unused_imports ) ] +use super::*; + +use the_module:: +{ + Fields, + +}; + +// xxx : implement for other collections + +use std:: +{ + borrow::Cow, +}; + +#[ test ] +fn bset_string_fields() +{ + let collection : BTreeSet< String > = bset! + [ + "a".to_string(), + "b".to_string(), + ]; + + // k, v + let got : BTreeSet< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = bset![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : BTreeSet< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = bset![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + +} + +#[ test ] +fn bset_str_fields() +{ + let collection : BTreeSet< &str > = bset! + [ + "a", + "b", + ]; + + // k, v + let got : BTreeSet< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = bset![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : BTreeSet< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = bset![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + +} diff --git a/module/core/reflect_tools/tests/inc/fundamental/fields_deque.rs b/module/core/reflect_tools/tests/inc/fundamental/fields_deque.rs new file mode 100644 index 0000000000..190d8fc57b --- /dev/null +++ b/module/core/reflect_tools/tests/inc/fundamental/fields_deque.rs @@ -0,0 +1,73 @@ +#[ allow( unused_imports ) ] +use super::*; + +use the_module:: +{ + Fields, + OptionalCow, +}; + +// xxx : implement for other collections + +use std:: +{ + borrow::Cow, +}; + +#[ test ] +fn deque_string_fields() +{ + let collection = deque! + [ + "a".to_string(), + "b".to_string(), + ]; + + // k, v + let got : VecDeque< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : VecDeque< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + + // k, OptionalCow< '_, str, () > + let got : VecDeque< _ > = Fields::< usize, OptionalCow< '_, str, () > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, OptionalCow::from( "a" ) ), ( 1, OptionalCow::from( "b" ) ) ]; + assert_eq!( got, exp ); + +} + +#[ test ] +fn deque_str_fields() +{ + let collection = deque! + [ + "a", + "b", + ]; + + // k, v + let got : VecDeque< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : VecDeque< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + + // k, OptionalCow< '_, str, () > + let got : VecDeque< _ > = Fields::< usize, OptionalCow< '_, str, () > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = deque![ ( 0, OptionalCow::from( "a" ) ), ( 1, OptionalCow::from( "b" ) ) ]; + assert_eq!( got, exp ); + +} diff --git a/module/core/reflect_tools/tests/inc/fundamental/fields_hset.rs b/module/core/reflect_tools/tests/inc/fundamental/fields_hset.rs new file mode 100644 index 0000000000..fddc44dc94 --- /dev/null +++ b/module/core/reflect_tools/tests/inc/fundamental/fields_hset.rs @@ -0,0 +1,60 @@ +#[ allow( unused_imports ) ] +use super::*; + +use the_module:: +{ + Fields, +}; + +// xxx : implement for other collections + +use std:: +{ + borrow::Cow, +}; + +#[ test ] +fn hset_string_fields() +{ + let collection : HashSet< String > = hset! + [ + "a".to_string(), + "b".to_string(), + ]; + + // k, v + let got : HashSet< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + assert!( got.contains(&( 0, "a" ) ) || got.contains(&( 1, "a" ) ) ); + assert!( got.contains(&( 0, "b" ) ) || got.contains(&( 1, "b" ) ) ); + + // k, Option< Cow< '_, str > > + let got : HashSet< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + assert!( got.contains(&( 0, Some( Cow::Borrowed( "a" ) ) ) ) || got.contains(&( 1, Some( Cow::Borrowed( "a" ) ) ) ) ); + assert!( got.contains(&( 0, Some( Cow::Borrowed( "b" ) ) ) ) || got.contains(&( 1, Some( Cow::Borrowed( "b" ) ) ) ) ); + +} + +#[ test ] +fn hset_str_fields() +{ + let collection : HashSet< &str > = hset! + [ + "a", + "b", + ]; + + // k, v + let got : HashSet< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + assert!( got.contains(&( 0, "a" ) ) || got.contains(&( 1, "a" ) ) ); + assert!( got.contains(&( 0, "b" ) ) || got.contains(&( 1, "b" ) ) ); + + // k, Option< Cow< '_, str > > + let got : HashSet< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + assert!( got.contains(&( 0, Some( Cow::Borrowed( "a" ) ) ) ) || got.contains(&( 1, Some( Cow::Borrowed( "a" ) ) ) ) ); + assert!( got.contains(&( 0, Some( Cow::Borrowed( "b" ) ) ) ) || got.contains(&( 1, Some( Cow::Borrowed( "b" ) ) ) ) ); + +} diff --git a/module/core/reflect_tools/tests/inc/fundamental/fields_llist.rs b/module/core/reflect_tools/tests/inc/fundamental/fields_llist.rs new file mode 100644 index 0000000000..dc93d87c0a --- /dev/null +++ b/module/core/reflect_tools/tests/inc/fundamental/fields_llist.rs @@ -0,0 +1,73 @@ +#[ allow( unused_imports ) ] +use super::*; + +use the_module:: +{ + Fields, + OptionalCow, +}; + +// xxx : implement for other collections + +use std:: +{ + borrow::Cow, +}; + +#[ test ] +fn llist_string_fields() +{ + let collection = llist! + [ + "a".to_string(), + "b".to_string(), + ]; + + // k, v + let got : LinkedList< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : LinkedList< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + + // k, OptionalCow< '_, str, () > + let got : LinkedList< _ > = Fields::< usize, OptionalCow< '_, str, () > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, OptionalCow::from( "a" ) ), ( 1, OptionalCow::from( "b" ) ) ]; + assert_eq!( got, exp ); + +} + +#[ test ] +fn llist_str_fields() +{ + let collection = llist! + [ + "a", + "b", + ]; + + // k, v + let got : LinkedList< _ > = Fields::< usize, &str >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, "a" ), ( 1, "b" ) ]; + assert_eq!( got, exp ); + + // k, Option< Cow< '_, str > > + let got : LinkedList< _ > = Fields::< usize, Option< Cow< '_, str > > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, Some( Cow::Borrowed( "a" ) ) ), ( 1, Some( Cow::Borrowed( "b" ) ) ) ]; + assert_eq!( got, exp ); + + // k, OptionalCow< '_, str, () > + let got : LinkedList< _ > = Fields::< usize, OptionalCow< '_, str, () > >::fields( &collection ).collect(); + assert_eq!( got.len(), 2 ); + let exp = llist![ ( 0, OptionalCow::from( "a" ) ), ( 1, OptionalCow::from( "b" ) ) ]; + assert_eq!( got, exp ); + +} diff --git a/module/core/reflect_tools/tests/inc/mod.rs b/module/core/reflect_tools/tests/inc/mod.rs index de4b0b494e..d0ec8fff41 100644 --- a/module/core/reflect_tools/tests/inc/mod.rs +++ b/module/core/reflect_tools/tests/inc/mod.rs @@ -12,6 +12,10 @@ mod fundamental mod fields_vec; mod fields_hmap; mod fields_bmap; + mod fields_bset; + mod fields_deque; + mod fields_hset; + mod fields_llist; }