This crate provides a way to transform an enum with associated data into a hashmap. This idea came to me as I was working on my UI library.
I wanted to implement styling in a very flexible way. Essentially, every style property is optional unless it's defined. This would have been extremely annoying to implement with a struct as all properties would have had to be an Option. Instead, I just simply create my enum with associated data and transform it into a map. I can later easily access each value with an iterator and manipulate it however I want.
[dependencies]
enum2map = "0.1"The way to use the crate is very simple. Define an enum with associated data and derive Enum2Map.
#[derive(Debug,PartialEq,Eq,Clone,Enum2Map)]pubenumTestValue{Padding(usize),Margin(String),}Then you can use generic getters and setters or the getter and setter for each property with the new enum that was generated.
pubenumTestValueKey{Padding,Margin,}letmut map = TestValueMap::new();
map.get(TestValueKey::Margin);
map.get(TestValueKey::Padding);
map.get_or_default(TestValueKey::Padding);
map.get_or_default(TestValueKey::Padding);
map.set(TestValue::Padding(10));
map.set(TestValue::Margin("string test".to_string()));As well as the getters and setters for each value in your enum:
map.set_padding(50);
map.set_margin("another test".to_string());
map.get_padding();
map.get_margin();The derive will first generate the keys from the enum provided:
pubenumTestValueKey{Padding,Margin,}It will then generate a struct with the generic getters and setters you saw in the examples. It will also generate a getter and setter for each value in your enum. The API was written to follow the HashMap API as closely as I could.
pubstructTestValueMap{pubvalues: std::collections::HashMap<TestValueKey,TestValue>,}implTestValueMap{pubfnnew() -> Self{Self{values: std::collections::HashMap::new(),}}pubfninsert(&mutself,value:TestValue) -> Option<TestValue>{match value {TestValue::Padding(val) => {self.values.insert(TestValueKey::Padding,TestValue::Padding(val))}TestValue::Margin(val) => {self.values.insert(TestValueKey::Margin,TestValue::Margin(val))}}}pubfnget(&self,key:TestValueKey) -> Option<&TestValue>{self.values.get(&key)}pubfnget_or_default(&self,key:TestValueKey) -> TestValue{matchself.values.get(&key){Some(value) => value.clone(),None => {match key {TestValueKey::Padding => TestValue::Padding(Default::default()),TestValueKey::Margin => TestValue::Margin(Default::default()),}}}}pubfnset(&mutself,value:TestValue) -> Option<TestValue>{match value {TestValue::Padding(val) => {self.values.insert(TestValueKey::Padding,TestValue::Padding(val))}TestValue::Margin(val) => {self.values.insert(TestValueKey::Margin,TestValue::Margin(val))}}}pubfnget_padding(&self) -> usize{matchself.values.get(&TestValueKey::Padding){Some(TestValue::Padding(value)) => value.clone(),None => Default::default(),
_ => {::core::panicking::panic_fmt(format_args!("Unexpected condition: Didn\'t find type {0} for {1}","usize","Padding",),);}}}pubfnget_margin(&self) -> String{matchself.values.get(&TestValueKey::Margin){Some(TestValue::Margin(value)) => value.clone(),None => Default::default(),
_ => {::core::panicking::panic_fmt(format_args!("Unexpected condition: Didn\'t find type {0} for {1}","String","Margin",),);}}}pubfnset_padding(&mutself,val:usize) -> Option<usize>{ifletSome(TestValue::Padding(old_value))
= self.values.insert(TestValueKey::Padding,TestValue::Padding(val)){returnSome(old_value);}None}pubfnset_margin(&mutself,val:String) -> Option<String>{ifletSome(TestValue::Margin(old_value))
= self.values.insert(TestValueKey::Margin,TestValue::Margin(val)){returnSome(old_value);}None}}- Better error handling.
- Handle cases where the enum has no associated data.
- Better documentation.