use std::convert::TryFrom;
use std::fmt;
use std::str::FromStr;
pub mod constraint {
use super::Prefix;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Constraint {
None,
UnitOnly,
UnitAndAbove,
UnitAndBelow,
Custom(Vec<Prefix>),
}
impl AsRef<Constraint> for Constraint {
fn as_ref(&self) -> &Self {
self
}
}
}
pub use constraint::Constraint;
use crate::{Result, SIUnitsError};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum Prefix {
Yocto = -24,
Zepto = -21,
Atto = -18,
Femto = -15,
Pico = -12,
Nano = -9,
Micro = -6,
Milli = -3,
Unit = 0,
Kilo = 3,
Mega = 6,
Giga = 9,
Tera = 12,
Peta = 15,
Exa = 18,
Zetta = 21,
Yotta = 24,
}
impl Prefix {
pub fn exponent(&self) -> i32 {
*self as i32
}
}
impl FromStr for Prefix {
type Err = SIUnitsError;
fn from_str(s: &str) -> Result<Self> {
match s {
"Yocto" | "yocto" | "y" => Ok(Self::Yocto),
"Zepto" | "zepto" | "z" => Ok(Self::Zepto),
"Atto" | "atto" | "a" => Ok(Self::Atto),
"Femto" | "femto" | "f" => Ok(Self::Femto),
"Pico" | "pico" | "p" => Ok(Self::Pico),
"Nano" | "nano" | "n" => Ok(Self::Nano),
"Micro" | "micro" | "µ" => Ok(Self::Micro),
"Milli" | "milli" | "m" => Ok(Self::Milli),
"Kilo" | "kilo" | "k" => Ok(Self::Kilo),
"Mega" | "mega" | "M" => Ok(Self::Mega),
"Giga" | "giga" | "G" => Ok(Self::Giga),
"Tera" | "tera" | "T" => Ok(Self::Tera),
"Peta" | "peta" | "P" => Ok(Self::Peta),
"Exa" | "exa" | "E" => Ok(Self::Exa),
"Zetta" | "zetta" | "Z" => Ok(Self::Zetta),
"Yotta" | "yotta" | "Y" => Ok(Self::Yotta),
_ => Err(SIUnitsError::ExponentParsing(s.to_string())),
}
}
}
impl From<&Prefix> for &str {
fn from(prefix: &Prefix) -> &'static str {
match prefix {
Prefix::Yocto => "y",
Prefix::Zepto => "z",
Prefix::Atto => "a",
Prefix::Femto => "f",
Prefix::Pico => "p",
Prefix::Nano => "n",
Prefix::Micro => "µ",
Prefix::Milli => "m",
Prefix::Unit => "",
Prefix::Kilo => "k",
Prefix::Mega => "M",
Prefix::Giga => "G",
Prefix::Tera => "T",
Prefix::Peta => "P",
Prefix::Exa => "E",
Prefix::Zetta => "Z",
Prefix::Yotta => "Y",
}
}
}
impl fmt::Display for Prefix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s: &'static str = self.into();
write!(f, "{}", s)
}
}
impl TryFrom<i32> for Prefix {
type Error = SIUnitsError;
fn try_from(value: i32) -> Result<Self> {
match value {
-24 => Ok(Self::Yocto),
-21 => Ok(Self::Zepto),
-18 => Ok(Self::Atto),
-15 => Ok(Self::Femto),
-12 => Ok(Self::Pico),
-9 => Ok(Self::Nano),
-6 => Ok(Self::Micro),
-3 => Ok(Self::Milli),
0 => Ok(Self::Unit),
3 => Ok(Self::Kilo),
6 => Ok(Self::Mega),
9 => Ok(Self::Giga),
12 => Ok(Self::Tera),
15 => Ok(Self::Peta),
18 => Ok(Self::Exa),
21 => Ok(Self::Zetta),
24 => Ok(Self::Yotta),
_ => Err(SIUnitsError::ExponentParsing(format!(
"Provided value should be a multiple of 3, between -24 and 24, got `{}` instead",
value
))),
}
}
}