use std::ops::{DivAssign, MulAssign}; #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Unit { Ampere, Watt, Volt, Ohm, None, } use Unit::*; #[derive(Debug)] pub struct UnknownUnit; impl TryFrom for char { type Error = UnknownUnit; fn try_from(value: Unit) -> Result { match value { Ampere => Ok('A'), Watt => Ok('W'), Volt => Ok('V'), Ohm => Ok('Ω'), None => Err(UnknownUnit), } } } impl TryFrom for Unit { type Error = UnknownUnit; fn try_from(value: char) -> Result { match value { 'V' => Ok(Volt), 'A' => Ok(Ampere), 'W' => Ok(Watt), 'Ω' => Ok(Ohm), _ => Err(UnknownUnit), } } } impl TryFrom<&str> for Unit { type Error = (); fn try_from(value: &str) -> Result { match value { "V" | "volt" | "volts" => Ok(Volt), "A" | "amp" | "amps" | "ampere" | "amperes" => Ok(Ampere), "W" | "watt" | "watts" => Ok(Watt), "Ω" | "ohm" | "ohms" => Ok(Ohm), "" => Ok(None), _ => Err(()), } } } impl MulAssign for Unit { fn mul_assign(&mut self, rhs: Unit) { *self = match (*self, rhs) { (Ampere, Volt) | (Volt, Ampere) => Watt, (Ampere, Ohm) | (Ohm, Ampere) => Volt, (Watt, _) | (_, Watt) | (Ampere, Ampere) | (Volt, Volt) | (Ohm, Ohm) => { panic!("Unavailable unit") } (Volt, Ohm) | (Ohm, Volt) => panic!("Unknown unit"), (t, None) => t, (None, t) => t, } } } impl DivAssign for Unit { fn div_assign(&mut self, rhs: Unit) { *self = match (*self, rhs) { (t, None) => t, // FIXME: bodge to allow calculating parallel circuit // resistance (1 / sum(1 / R_i)) (None, Ohm) => Ohm, (None, _) => panic!("idk the inverse of any of the types"), (a, b) if a == b => None, (Ampere, Ampere) | (Watt, Watt) | (Volt, Volt) | (Ohm, Ohm) => None, (Watt, Ampere) => Volt, (Watt, Volt) => Ampere, (Volt, Ampere) => Ohm, (Volt, Ohm) => Ampere, (Ampere, Volt) | (Ampere, Ohm) | (Ohm, Volt) | (Ohm, Ampere) | (Watt, Ohm) | (_, Watt) => { panic!("Unavailable unit") } } } }