Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Enum with data to HashMap

github crates.io

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"

Examples

The way to use the crate is very simple. Define an enum with associated data and derive Enum2Map.

#[derive(Debug, PartialEq, Eq, Clone, Enum2Map)]
pub enum TestValue {
    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.

pub enum TestValueKey {
    Padding,
    Margin,
}

let mut 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();

How it works

The derive will first generate the keys from the enum provided:

pub enum TestValueKey {
    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.

pub struct TestValueMap {
    pub values: std::collections::HashMap<TestValueKey, TestValue>,
}
impl TestValueMap {
    pub fn new() -> Self {
        Self {
            values: std::collections::HashMap::new(),
        }
    }
    pub fn insert(&mut self, 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))
            }
        }
    }
    pub fn get(&self, key: TestValueKey) -> Option<&TestValue> {
        self.values.get(&key)
    }
    pub fn get_or_default(&self, key: TestValueKey) -> TestValue {
        match self.values.get(&key) {
            Some(value) => value.clone(),
            None => {
                match key {
                    TestValueKey::Padding => TestValue::Padding(Default::default()),
                    TestValueKey::Margin => TestValue::Margin(Default::default()),
                }
            }
        }
    }
    pub fn set(&mut self, 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))
            }
        }
    }
    pub fn get_padding(&self) -> usize {
        match self.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",
                    ),
                );
            }
        }
    }
    pub fn get_margin(&self) -> String {
        match self.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",
                    ),
                );
            }
        }
    }
    pub fn set_padding(&mut self, val: usize) -> Option<usize> {
        if let Some(TestValue::Padding(old_value))
            = self.values.insert(TestValueKey::Padding, TestValue::Padding(val))
        {
            return Some(old_value);
        }
        None
    }
    pub fn set_margin(&mut self, val: String) -> Option<String> {
        if let Some(TestValue::Margin(old_value))
            = self.values.insert(TestValueKey::Margin, TestValue::Margin(val))
        {
            return Some(old_value);
        }
        None
    }
}

Future Work

  • Better error handling.
  • Handle cases where the enum has no associated data.
  • Better documentation.

About

Enum constructors to HashMap.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages