impl {{ name }} { // Method to get help messages as a HashMap, where the key is the field name and the // value is a tuple of the default value and help message. pub fn get_help() -> std::collections::HashMap)> { let mut help_map = std::collections::HashMap::new(); {% for field in fields %} // If the field is a custom type, recursively get its help information. {% if !contains(["usize", "i16", "i32", "i64", "u16", "u32", "u64", "f32", "f64", "bool", "String"], field.typ) && !field.attr_parse %} let nested_help = {{ field.typ }}::get_help(); for (nested_key, nested_value) in nested_help { help_map.insert(nested_key, nested_value); } {% else %} // Handle primitive types let key = "{{ field.attr_name }}".to_string(); let help = {% if field.attr_help.is_empty() %} None {% else %} Some("{{ field.attr_help }}".to_string()) {% endif %}; let value = ("{{ field.attr_default }}".to_string(), help); help_map.insert(key, value); {% endif %} {% endfor %} help_map } pub fn init() -> Result<{{ name }}, &'static str> { let mut key: &str; {% for field in fields %} {% if field.attr_name.is_empty() %} key = "{{ uppersnake((name.clone() + "_" + field.name.as_str()).as_str()) }}"; {% else %} key = "{{ field.attr_name }}"; {% endif %} {% if contains(["usize","i16","i32","i64","u16","u32","u64","f32","f64","bool"], field.typ) %} let {{ field.name }}: Option<{{ field.typ }}> = match std::env::var(key) { Ok(val) => match val.to_lowercase().parse() { Ok(v) => Some(v), Err(_) => { panic!("EnvConfig: {} except a value of [{{ field.typ }}]", key); }, }, Err(err) => { {% if field.attr_default.is_empty() %} Some(Default::default()) {% else %} Some("{{ field.attr_default }}".parse().unwrap()) {% endif %} } }; {% else if field.typ == "String" %} let {{ field.name }}: Option<{{ field.typ }}> = match std::env::var(key) { Ok(val) => Some(val), Err(err) => { {% if field.attr_default.is_empty() %} Some(Default::default()) {% else %} Some("{{ field.attr_default }}".parse().unwrap()) {% endif %} } }; {% else if field.attr_parse %} let {{ field.name }}: Option<{{ field.typ }}> = match std::env::var(key) { Ok(val) => match val.parse::<{{ field.typ }}>() { Ok(v) => Some(v), Err(_) => { panic!("EnvConfig: {} except a value of [{{ field.typ }}]", key); }, }, Err(_) => { {% if field.attr_default.is_empty() %} Default::default().parse::<{{ field.typ }}>().ok() {% else %} "{{ field.attr_default }}".parse::<{{ field.typ }}>().ok() {% endif %} } }; {% else %} let {{ field.name }}: Option<{{ field.typ }}> = match {{ field.typ }}::init() { Ok(v) => Some(v), Err(_) => None, }; {% endif %} {% endfor %} Ok({{ name }} { {% for field in fields %} {% if field.optional %} {{ field.name }}: {{ field.name }}, {% else %} {{ field.name }}: {{ field.name }}.ok_or("Build failed: missing {{ field.name }}")?, {% endif %} {% endfor %} }) } }