use std::error; use std::fmt; use std::convert::Infallible; pub mod bytes; pub trait Conversion { const UNIT: &'static str; type Output: fmt::Display; type Unit: fmt::Display = Self::Output; type Error: Into = ConversionError; fn convert(&self, input: &str) -> Result<(Self::Output, Option), Self::Error>; } #[derive(Debug)] pub struct ConversionError(String); impl error::Error for ConversionError{} impl fmt::Display for ConversionError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "conversion failed: {}", self.0) } } impl From for ConversionError { fn from(from: Infallible) -> Self { match from {} } } fn print_output((value, units): (T, Option)) where T: fmt::Display, U: fmt::Display { println!("{}", value); if let Some(units) = units { eprintln!("{}", units); } } /// Dispatch a conversion of `value` for type `unit` and print the result to stdout. pub fn dispatch_out(unit: impl AsRef, value: impl AsRef) -> Result<(), ConversionError> { match unit.as_ref() { bytes::Bytes::UNIT => print_output(bytes::Bytes.convert(value.as_ref())?), name => return Err(ConversionError(format!("Unknown unit {}", name))), } Ok(()) }