make_fields 0.1.0

Tiny derive macro to work with fields inspired by lens's makeFields
Documentation
use make_fields::HasFields;

use std::collections::HashMap;
use std::default::Default;

#[derive(HasFields)]
struct AppConfig {
    db: HashMap<String, String>,
    port: u16,
    host: String,
}

#[derive(HasFields)]
struct SomeOtherDbHolder {
    #[skip_class]
    db: HashMap<String, String>,
}

impl Default for AppConfig {
    fn default() -> AppConfig {
        AppConfig {
            db: HashMap::new(),
            port: 3000,
            host: "127.0.0.1".to_string(),
        }
    }
}

fn connect_to_server<T, Port, Host>(holder: &T) -> Result<(&Port, &Host), ()>
where
    T: HasPort<Port = Port> + HasHost<Host = Host>,
{
    Ok((holder.port(), holder.host()))
}

fn get_hello_world_from_db<T>(db_handle: &T) -> Option<String>
where
    T: HasDb<Db = HashMap<String, String>>,
{
    db_handle.db().get("hello_world").cloned()
}

#[test]
fn test_make_fields_works() {
    let config = AppConfig::default();

    assert_eq!(config.db(), &HashMap::new());
    assert_eq!(config.port(), &3000);
    assert_eq!(config.host(), "127.0.0.1");
}

#[test]
fn test_function_that_uses_field_traits_works() {
    let config = AppConfig::default();

    let result = connect_to_server(&config);

    assert_eq!(result, Ok((config.port(), config.host())));
}

#[test]
fn test_function_that_uses_field_traits_works_with_different_objects() {
    let config = AppConfig::default();
    let other_holder = SomeOtherDbHolder { db: HashMap::new() };

    let result1 = get_hello_world_from_db(&config);
    let result2 = get_hello_world_from_db(&other_holder);

    assert_eq!(None, result1);
    assert_eq!(None, result2);
}