use crate::{Error, Result};
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::ops;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Digit {
I,
V,
X,
L,
C,
D,
M,
}
impl Digit {
pub fn from_int<T: Into<u32>>(num: T) -> Result<Digit> {
let num: u32 = num.into();
use self::Digit::*;
match num {
1 => Ok(I),
5 => Ok(V),
10 => Ok(X),
50 => Ok(L),
100 => Ok(C),
500 => Ok(D),
1000 => Ok(M),
_ => Err(Error::InvalidNumber(num)),
}
}
}
impl Digit {
pub fn from_char(c: char) -> Result<Digit> {
use self::Digit::*;
match c.to_uppercase().next() {
Some('I') => Ok(I),
Some('V') => Ok(V),
Some('X') => Ok(X),
Some('L') => Ok(L),
Some('C') => Ok(C),
Some('D') => Ok(D),
Some('M') => Ok(M),
_ => Err(Error::InvalidDigit(c)),
}
}
pub fn from_byte(b: u8) -> Result<Digit> {
use self::Digit::*;
match b {
b'I' | b'i' => Ok(I),
b'V' | b'v' => Ok(V),
b'X' | b'x' => Ok(X),
b'L' | b'l' => Ok(L),
b'C' | b'c' => Ok(C),
b'D' | b'd' => Ok(D),
b'M' | b'm' => Ok(M),
_ => Err(Error::InvalidDigit(b.into())),
}
}
pub fn to_lowercase(self) -> char {
use self::Digit::*;
match self {
I => 'i',
V => 'v',
X => 'x',
L => 'l',
C => 'c',
D => 'd',
M => 'm',
}
}
pub fn to_uppercase(self) -> char {
use self::Digit::*;
match self {
I => 'I',
V => 'V',
X => 'X',
L => 'L',
C => 'C',
D => 'D',
M => 'M',
}
}
}
unsafe impl Send for Digit {}
unsafe impl Sync for Digit {}
impl From<Digit> for u32 {
fn from(digit: Digit) -> u32 {
*digit
}
}
impl<'a> From<&'a Digit> for char {
fn from(digit: &'a Digit) -> char {
digit.to_uppercase()
}
}
impl Display for Digit {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(f, "{}", char::from(self))
}
}
impl ops::Deref for Digit {
type Target = u32;
fn deref(&self) -> &u32 {
use self::Digit::*;
match *self {
I => &1,
V => &5,
X => &10,
L => &50,
C => &100,
D => &500,
M => &1000,
}
}
}