diff --git a/.idea/micronfig.iml b/.idea/micronfig.iml index d5315f5..cd3603f 100644 --- a/.idea/micronfig.iml +++ b/.idea/micronfig.iml @@ -7,9 +7,11 @@ + + diff --git a/examples/e01_the_cave/src/main.rs b/examples/e01_the_cave/src/main.rs index 06b673a..569d7bc 100644 --- a/examples/e01_the_cave/src/main.rs +++ b/examples/e01_the_cave/src/main.rs @@ -1,9 +1,9 @@ use std::fmt::{Display, Formatter}; use std::str::FromStr; + fn main() { - let echo: String = micronfig::get("ECHO") - .expect("ECHO configuration value to be defined"); + let echo: String = micronfig::required("ECHO"); println!("ECHOing back: {echo}"); } diff --git a/examples/e02_quick_math/src/main.rs b/examples/e02_quick_math/src/main.rs index 66b04de..8288d8b 100644 --- a/examples/e02_quick_math/src/main.rs +++ b/examples/e02_quick_math/src/main.rs @@ -1,6 +1,23 @@ use std::fmt::{Display, Formatter}; use std::str::FromStr; + +fn main() { + let first: u64 = micronfig::required("FIRST"); + let second: u64 = micronfig::required("SECOND"); + let operator: Operator = micronfig::required("OPERATOR"); + + let result = match operator { + Operator::Sum => first + second, + Operator::Subtraction => first - second, + Operator::Multiplication => first * second, + Operator::Division => first / second, + }; + + println!("{first} {operator} {second} = {result}") +} + + pub enum Operator { Sum, Subtraction, @@ -31,22 +48,4 @@ impl Display for Operator { Self::Division => "/", }) } -} - -fn main() { - let first: u64 = micronfig::get("FIRST") - .expect("FIRST operand to be properly defined"); - let second: u64 = micronfig::get("SECOND") - .expect("SECOND operand to be properly defined"); - let operator: Operator = micronfig::get("OPERATOR") - .expect("OPERATOR to be properly defined"); - - let result = match operator { - Operator::Sum => first + second, - Operator::Subtraction => first - second, - Operator::Multiplication => first * second, - Operator::Division => first / second, - }; - - println!("{first} {operator} {second} = {result}") -} +} \ No newline at end of file diff --git a/examples/e03_order_a_pizza/Cargo.toml b/examples/e03_order_a_pizza/Cargo.toml new file mode 100644 index 0000000..3c1211b --- /dev/null +++ b/examples/e03_order_a_pizza/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "e03_order_a_pizza" +description = "Order a pizza using micronfig!" +version = "0.0.0" +edition = "2021" + +[dependencies] +micronfig = { path = "../.." } diff --git a/examples/e03_order_a_pizza/src/main.rs b/examples/e03_order_a_pizza/src/main.rs new file mode 100644 index 0000000..f0c70b4 --- /dev/null +++ b/examples/e03_order_a_pizza/src/main.rs @@ -0,0 +1,114 @@ +use std::fmt::Formatter; +use std::net::IpAddr; +use std::str::FromStr; + +fn main() { + // The name of the person who ordered the pizza. + let full_name: String = micronfig::required("FULLNAME"); + + // The (IP) address the pizza should be delivered to. + let destination: IpAddr = micronfig::required("DESTINATION"); + + // The base of the pizza to add toppings on. + let pizza_base: PizzaBase = micronfig::required("PIZZABASE"); + + // The toppings to add to the pizza. + let pizza_toppings: PizzaToppingsList = micronfig::optional("PIZZATOPPINGS") + .unwrap_or_else(|| PizzaToppingsList{ list: vec![] }); + + // Let's print the order! + println!("Pizza Order"); + println!("==========="); + println!(); + println!("Base:"); + println!("- {}", &pizza_base); + println!(); + println!("Toppings:"); + for topping in pizza_toppings.list { + println!("- {}", &topping); + }; + println!(); + println!("Deliver to:"); + println!("{} @ {}", &full_name, &destination) +} + + +/// A possible base of pizza. +enum PizzaBase { + /// Just the pizza dough, with nothing else on top of it. + Blank, + /// Pizza dough with tomato on top. + Red, + /// Pizza dough with mozzarella on top. + White, + /// Pizza dough with both tomato and mozzarella on top. + Margherita, +} + +impl FromStr for PizzaBase { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + // Italian + "vuota" => Ok(Self::Blank), + "stria" => Ok(Self::Blank), + "rossa" => Ok(Self::Red), + "marinara" => Ok(Self::Red), + "pomodoro" => Ok(Self::Red), + "bianca" => Ok(Self::White), + "mozzarella" => Ok(Self::White), + "regina" => Ok(Self::Margherita), + "margherita" => Ok(Self::Margherita), + "normale" => Ok(Self::Margherita), + "entrambi" => Ok(Self::Margherita), + // English + "blank" => Ok(Self::Blank), + "red" => Ok(Self::Red), + "tomato" => Ok(Self::Red), + "white" => Ok(Self::White), + "cheese" => Ok(Self::White), + "both" => Ok(Self::Margherita), + "normal" => Ok(Self::Margherita), + // Unknown + _ => Err("Unknown pizza base; ensure you have written the name in either English or Italian!"), + } + } +} + +impl std::fmt::Display for PizzaBase { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + PizzaBase::Blank => "Blank (Empty)", + PizzaBase::Red => "Red (Tomato)", + PizzaBase::White => "White (Mozzarella)", + PizzaBase::Margherita => "Margherita (Tomato + Mozzarella)" + }) + } +} + +/// The toppings +struct PizzaToppingsList { + pub list: Vec +} + +impl FromStr for PizzaToppingsList { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let list: Vec = s.split(",").map(|s| s.to_string()).collect(); + + for topping in list.iter() { + // Ensure compatibility with https://github.com/rust-lang/rust/pull/70645 + if ["pineapple", "ananas"].contains(&topping.as_str()) { + return Err("Ruining pizzas is not allowed by the Rust compiler.") + } + } + + Ok( + PizzaToppingsList { + list + } + ) + } +} \ No newline at end of file