use std::{error::Error, fmt::Display};
#[derive(Debug, Clone, Copy)]
pub struct TempOutOfRange;
impl Display for TempOutOfRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"provided temperature does not fit in range".fmt(f)
}
}
impl Error for TempOutOfRange {}
#[derive(Default)]
pub struct Celsius {
value: i8,
}
impl Celsius {
const OFFSET: i8 = 0;
pub fn new(degrees: i16) -> Result<Self, TempOutOfRange> {
let value = degrees + Self::OFFSET as i16;
match value.try_into() {
Ok(value) => Ok(Self { value }),
Err(_) => Err(TempOutOfRange),
}
}
pub fn raw_value(&self) -> u8 {
self.value as u8
}
pub fn degrees(&self) -> i16 {
self.value as i16 - Self::OFFSET as i16
}
pub fn from_raw(value: u8) -> Self {
Self { value: value as i8 }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn temperature() {
assert_eq!(Celsius::new(0).unwrap().raw_value(), 0);
assert_eq!(Celsius::new(40).unwrap().raw_value(), 40);
assert_eq!(Celsius::from_raw(40).value, Celsius::new(40).unwrap().value);
assert_eq!(Celsius::new(-1).unwrap().raw_value(), 255);
}
}