|
|
|
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> = ConversionError;
|
|
|
|
|
|
|
|
fn convert(&self, input: &str) -> Result<(Self::Output, Option<Self::Unit>), 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<Infallible> for ConversionError
|
|
|
|
{
|
|
|
|
fn from(from: Infallible) -> Self
|
|
|
|
{
|
|
|
|
match from {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_output<T,U>((value, units): (T, Option<U>))
|
|
|
|
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<str>, value: impl AsRef<str>) -> 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(())
|
|
|
|
}
|