Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
72 lines (62 sloc) 2.19 KB
mod error;
use error::Error;
use std::fmt;
use std::str::FromStr;
pub trait Temperature: Sized {
const ABSOLUTE_ZERO: f64;
const SYMBOL: &'static str;
fn new(value: f64) -> Option<Self>;
fn value(&self) -> f64;
}
macro_rules! temperature {
($temp:ident $sym:literal $abs_zero:literal) => {
#[derive(Debug)]
pub struct $temp{ value: f64 }
impl Temperature for $temp {
const ABSOLUTE_ZERO: f64 = $abs_zero;
const SYMBOL: &'static str = $sym;
fn new(val: f64) -> Option<Self> {
if val >= Self::ABSOLUTE_ZERO {
Some($temp{ value: val })
} else { None }
}
fn value(&self) -> f64 { self.value }
}
impl FromStr for $temp {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
$temp::new(s.parse()?).ok_or(Error::BelowAbsoluteZero)
}
}
impl fmt::Display for $temp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", self.value, Self::SYMBOL)
}
}
}
}
macro_rules! impl_from_temp {
($from:ident $to:ident $f:expr) => {
impl From<$from> for $to {
fn from(from: $from) -> Self {
$to::new($f(from.value)).unwrap()
}
}
}
}
temperature!(Celsius "°C" -273.15);
temperature!(Fahrenheit "°F" -459.67);
temperature!(Kelvin "K" 0.0);
temperature!(Rankine "°R" 0.0);
impl_from_temp!(Fahrenheit Celsius |x| (x - 32.0) * 5.0 / 9.0);
impl_from_temp!(Kelvin Celsius |x| x - 273.15);
impl_from_temp!(Rankine Celsius |x| x - 491.67 * 5.0 / 9.0);
impl_from_temp!(Celsius Fahrenheit |x| x * 9.0 / 5.0 + 32.0);
impl_from_temp!(Kelvin Fahrenheit |x| (x - 273.15) * 9.0 / 5.0 + 32.0);
impl_from_temp!(Rankine Fahrenheit |x| x - 459.67);
impl_from_temp!(Celsius Kelvin |x| x + 273.15);
impl_from_temp!(Fahrenheit Kelvin |x| (x - 32.0) * 5.0 / 9.0 + 273.15);
impl_from_temp!(Rankine Kelvin |x| x * 5.0 / 9.0);
impl_from_temp!(Celsius Rankine |x| x * 9.0 / 5.0 + 491.67);
impl_from_temp!(Fahrenheit Rankine |x| x + 459.67);
impl_from_temp!(Kelvin Rankine |x| x * 1.803);