utterance 0.1.4

A parser library for creating readable, natural-language-inspired domain-specific languages.
Documentation
use std::fmt;

use crate::parser::expectation::NumberKind;

#[derive(Debug, Copy, Clone)]
pub enum Number {
    UnsignedInteger(usize),
    Integer(isize),
    Float(f64),
}

impl Number {
    pub(crate) fn try_convert_into(&mut self, kind: NumberKind) -> bool {
        let converted = match (*self, kind) {
            (Number::UnsignedInteger(n), NumberKind::Integer) => Some(Number::Integer(n as isize)),
            (Number::UnsignedInteger(n), NumberKind::Float) => Some(Number::Float(n as f64)),
            (Number::Integer(n), NumberKind::Float) => Some(Number::Float(n as f64)),

            (number, NumberKind::UnsignedInteger)
                if matches!(number, Number::UnsignedInteger(_)) =>
            {
                Some(number)
            }

            (number, NumberKind::Integer) if matches!(number, Number::Integer(_)) => Some(number),
            (number, NumberKind::Float) if matches!(number, Number::Float(_)) => Some(number),

            _ => None,
        };

        if let Some(value) = converted {
            *self = value;
            true
        } else {
            false
        }
    }
}

impl PartialEq for Number {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::UnsignedInteger(a), Self::UnsignedInteger(b)) => a == b,
            (Self::Integer(a), Self::Integer(b)) => a == b,
            (Self::Float(a), Self::Float(b)) => a.to_bits() == b.to_bits(),

            _ => false,
        }
    }
}

impl Eq for Number {}

impl fmt::Display for Number {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::UnsignedInteger(value) => write!(f, "unsigned integer: {value}"),
            Self::Integer(value) => write!(f, "integer: {value}"),
            Self::Float(value) => write!(f, "float: {value}"),
        }
    }
}

impl From<Number> for NumberKind {
    fn from(number: Number) -> Self {
        match number {
            Number::UnsignedInteger(_) => NumberKind::UnsignedInteger,
            Number::Integer(_) => NumberKind::Integer,
            Number::Float(_) => NumberKind::Float,
        }
    }
}