11//! Element attributes
22use std:: borrow:: Borrow ;
3- // #![deny(missing_docs)]
43use std:: ops:: Deref ;
54
65use anathema_store:: remotecell:: RemoteCell ;
@@ -10,12 +9,13 @@ use anathema_store::smallmap::{SmallIndex, SmallMap};
109use crate :: runtime:: elements:: ElementId ;
1110use crate :: runtime:: eval:: values:: TemplateValue ;
1211
12+ // All attributes for all elements
1313#[ derive( Debug ) ]
14- pub struct AllAttributes < ' bp > {
14+ pub ( crate ) struct AttributeRegistry < ' bp > {
1515 attributes : SecondaryMap < ElementId , Attributes < ' bp > > ,
1616}
1717
18- impl < ' bp > AllAttributes < ' bp > {
18+ impl < ' bp > AttributeRegistry < ' bp > {
1919 pub ( crate ) fn empty ( ) -> Self {
2020 Self {
2121 attributes : SecondaryMap :: empty ( ) ,
@@ -27,14 +27,15 @@ impl<'bp> AllAttributes<'bp> {
2727 }
2828}
2929
30+ // The access key for attributes.
3031#[ derive( Debug , Copy , Clone , PartialEq ) ]
31- pub enum ValueKey < ' bp > {
32+ pub ( crate ) enum ValueKey < ' bp > {
3233 Value ,
3334 Attribute ( & ' bp str ) ,
3435}
3536
3637impl ValueKey < ' _ > {
37- pub fn as_str ( & self ) -> & str {
38+ fn as_str ( & self ) -> & str {
3839 match self {
3940 ValueKey :: Value => "[value]" ,
4041 ValueKey :: Attribute ( name) => name,
@@ -48,12 +49,20 @@ impl Borrow<str> for ValueKey<'_> {
4849 }
4950}
5051
52+ /// Element attributes
53+ ///
54+ /// ```text
55+ /// text [foreground: "red", bold: true] "hello world"
56+ /// ```
57+ ///
58+ /// Attributes can be set / replaced or read, but never mutated because of the `RemoteCell`.
5159#[ derive( Debug ) ]
5260pub struct Attributes < ' bp > {
5361 inner : SmallMap < ValueKey < ' bp > , RemoteCell < TemplateValue < ' bp > > > ,
5462}
5563
5664impl < ' bp > Attributes < ' bp > {
65+ /// Create a new instance of en empty set of attributes
5766 pub fn empty ( ) -> Self {
5867 Self {
5968 inner : SmallMap :: empty ( ) ,
@@ -102,8 +111,9 @@ impl<'bp> Attributes<'bp> {
102111 self . inner . remove ( key)
103112 }
104113
105- pub ( crate ) fn get ( & self , key : & str ) -> Option < & RemoteCell < TemplateValue < ' bp > > > {
106- self . inner . get ( key)
114+ pub ( crate ) fn get ( & self , key : & str ) -> Option < & TemplateValue < ' bp > > {
115+ let val = self . inner . get ( key) ?;
116+ Some ( & * val)
107117 }
108118
109119 /// Get a value as a given type.
@@ -129,6 +139,7 @@ impl<'bp> Attributes<'bp> {
129139 pub fn value_as < ' a , T > ( & ' a self ) -> Option < T >
130140 where
131141 T : TryFrom < & ' a TemplateValue < ' bp > > ,
142+ T : ?Sized ,
132143 {
133144 self . inner
134145 . get ( & ValueKey :: Value )
@@ -177,12 +188,116 @@ impl<'bp> Attributes<'bp> {
177188 . flatten ( )
178189 }
179190
180- /// Iterate over attributes .
181- /// This will skip the value
182- pub fn iter ( & self ) -> impl Iterator < Item = ( & ValueKey < ' _ > , & RemoteCell < TemplateValue < ' bp > > ) > {
191+ /// Iterator of keys and values .
192+ /// NOTE: This will skip the value
193+ pub fn iter ( & self ) -> impl Iterator < Item = ( & str , & TemplateValue < ' bp > ) > {
183194 self . inner . iter ( ) . filter_map ( |( key, val) | match key {
184195 ValueKey :: Value => None ,
185- ValueKey :: Attribute ( _ ) => Some ( ( key, & * val) ) ,
196+ & ValueKey :: Attribute ( key ) => Some ( ( key, & * * val) ) ,
186197 } )
187198 }
199+
200+ /// Iterator of keys
201+ pub fn iter_keys ( & self ) -> impl Iterator < Item = & str > {
202+ self . inner . iter ( ) . filter_map ( |( key, _) | match key {
203+ ValueKey :: Value => None ,
204+ & ValueKey :: Attribute ( key) => Some ( key) ,
205+ } )
206+ }
207+
208+ /// Iterator of values
209+ pub fn iter_values ( & self ) -> impl Iterator < Item = & TemplateValue < ' bp > > {
210+ self . inner . iter ( ) . filter_map ( |( key, value) | match key {
211+ ValueKey :: Value => None ,
212+ & ValueKey :: Attribute ( _) => Some ( & * * value) ,
213+ } )
214+ }
215+ }
216+
217+ #[ cfg( test) ]
218+ mod test {
219+ use super :: * ;
220+
221+ fn attributes ( ) -> Attributes < ' static > {
222+ let mut attributes = Attributes :: empty ( ) ;
223+ attributes. set ( "int" , 1 ) ;
224+ attributes. set ( "strings" , vec ! [ "one" , "two" ] ) ;
225+ attributes. set ( "numbers" , vec ! [ 1 , 2 , 3 ] ) ;
226+ attributes. set (
227+ "mixed" ,
228+ TemplateValue :: List ( vec ! [ true . into( ) , 1 . into( ) , "string" . into( ) ] . into ( ) ) ,
229+ ) ;
230+ attributes
231+ }
232+
233+ #[ test]
234+ fn replace_attribute ( ) {
235+ let mut attributes = attributes ( ) ;
236+ assert_eq ! ( attributes. get_as:: <u32 >( "int" ) . unwrap( ) , 1 ) ;
237+ attributes. set ( "int" , 2 ) ;
238+ assert_eq ! ( attributes. get_as:: <u32 >( "int" ) . unwrap( ) , 2 ) ;
239+ }
240+
241+ #[ test]
242+ fn set_value ( ) {
243+ let mut attributes = attributes ( ) ;
244+ attributes. set ( "other" , 2 ) ;
245+ assert_eq ! ( attributes. get_as:: <u32 >( "other" ) . unwrap( ) , 2 ) ;
246+ }
247+
248+ #[ test]
249+ fn remove ( ) {
250+ let mut attributes = attributes ( ) ;
251+ attributes. remove ( "int" ) ;
252+ assert ! ( attributes. get( "int" ) . is_none( ) ) ;
253+ }
254+
255+ #[ test]
256+ fn get_attribute ( ) {
257+ let attributes = attributes ( ) ;
258+ assert_eq ! ( attributes. get( "int" ) , Some ( & TemplateValue :: Int ( 1 ) ) ) ;
259+ }
260+
261+ #[ test]
262+ fn get_attribute_as ( ) {
263+ let attributes = attributes ( ) ;
264+ assert_eq ! ( attributes. get_as:: <u8 >( "int" ) . unwrap( ) , 1 ) ;
265+ assert ! ( attributes. get_as:: <bool >( "int" ) . is_none( ) ) ;
266+ }
267+
268+ #[ test]
269+ fn get_value_as ( ) {
270+ let mut attributes = attributes ( ) ;
271+ attributes. set_value ( "hello world" ) ;
272+ assert_eq ! ( attributes. value_as:: <& str >( ) . unwrap( ) , "hello world" ) ;
273+
274+ attributes. set_value ( "hello world" . to_string ( ) ) ;
275+ assert_eq ! ( attributes. value_as:: <& str >( ) . unwrap( ) , "hello world" ) ;
276+ }
277+
278+ #[ test]
279+ fn iterate_as ( ) {
280+ let attributes = attributes ( ) ;
281+ let numbers = attributes. iter_as :: < u32 > ( "numbers" ) . collect :: < Vec < _ > > ( ) ;
282+ assert_eq ! ( numbers, vec![ 1 , 2 , 3 ] ) ;
283+
284+ let strings = attributes. iter_as :: < & str > ( "strings" ) . collect :: < Vec < _ > > ( ) ;
285+ assert_eq ! ( strings, vec![ "one" , "two" ] ) ;
286+ }
287+
288+ #[ test]
289+ fn iter ( ) {
290+ let attributes = attributes ( ) ;
291+ let mut iter = attributes. iter ( ) ;
292+ assert_eq ! ( ( "int" , & TemplateValue :: Int ( 1 ) ) , iter. next( ) . unwrap( ) ) ;
293+ }
294+
295+ #[ test]
296+ fn iter_keys ( ) {
297+ let attributes = attributes ( ) ;
298+ let mut iter = attributes. iter_keys ( ) ;
299+ assert_eq ! ( "int" , iter. next( ) . unwrap( ) ) ;
300+ assert_eq ! ( "strings" , iter. next( ) . unwrap( ) ) ;
301+ assert_eq ! ( "numbers" , iter. next( ) . unwrap( ) ) ;
302+ }
188303}
0 commit comments