![Build](https://github.com/a1akris/overwrite/actions/workflows/build.yml/badge.svg) # Overwrite A simple trait that defines how to overwrite a type by another types. Mainly useful to create an app configuration from different sources. ### Example ```rust use overwrite::Overwrite; struct Config { url: String, user: String, api_token: String, } impl Default for Config { fn default() -> Self { Self { url: "default".to_owned(), user: "default".to_owned(), api_token: "default".to_owned(), } } } struct CliArgs { url: Option, user: Option, api_token: Option } impl Overwrite for Config { fn overwrite_mut(&mut self, cli_args: CliArgs) -> &mut Self { // There is a blanket impl to overwrite values with Options. // Overwrite happens if the Option is Some. self.url.overwrite_mut(cli_args.url); self.user.overwrite_mut(cli_args.user); self.api_token.overwrite_mut(cli_args.api_token); self } } struct ConfFile { url: Option, user: Option, api_token: Option, } impl Overwrite for Config { fn overwrite_mut(&mut self, conf_file: ConfFile) -> &mut Self { self.url.overwrite_mut(conf_file.url); self.user.overwrite_mut(conf_file.user); self.api_token.overwrite_mut(conf_file.api_token); self } } struct EnvVars { url: Option, user: Option, api_token: Option, } impl Overwrite for Config { fn overwrite_mut(&mut self, env_vars: EnvVars) -> &mut Self { self.url.overwrite_mut(env_vars.url); self.user.overwrite_mut(env_vars.user); self.api_token.overwrite_mut(env_vars.api_token); self } } fn main() { let cli_args = parse_args(); let conf_file = read_conf_file(); let env_vars = parse_env(); // Note the precedense. `cli_args` have the highest precedense while default config values // have the lowest precedense. `conf_file` values will be overwritten by `env_vars` if env // vars are present. let config = Config::default() .overwrite(conf_file) .overwrite(env_vars) .overwrite(cli_args); assert_eq!(config.url, "default"); assert_eq!(config.user, "from_env_vars"); assert_eq!(config.api_token, "from_cli_args"); } fn parse_args() -> CliArgs { CliArgs { url: None, user: None, api_token: Some("from_cli_args".to_owned()), } } fn parse_env() -> EnvVars { EnvVars { url: None, user: Some("from_env_vars".to_owned()), api_token: None, } } fn read_conf_file() -> ConfFile { ConfFile { url: None, user: Some("from_conf_file".to_owned()), api_token: Some("from_conf_file".to_owned()), } } ``` As you have noticed the trait implementation is quite repetetive. There will be a proc macro to automatically derive it in the future versions. #### License Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.