trivet 3.1.0

The trivet Parser Library
Documentation
// Trivet
// Copyright (c) 2025 by Stacy Prowell.  All rights reserved.
// https://gitlab.com/binary-tools/trivet

//! Provide the different radices for numbers.

use std::fmt::{self, Debug, Display};

/// Number radices that are supported.
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub enum Radix {
    /// Binary is base two.
    Binary,
    /// Octal is base eight.
    Octal,
    /// Decimal is base 10.
    #[default]
    Decimal,
    /// Hexadecimal is base 16.
    Hexadecimal,
}

impl Radix {
    /// Get the value of each radix.
    pub fn value(&self) -> u32 {
        match self {
            Radix::Binary => 2,
            Radix::Octal => 8,
            Radix::Decimal => 10,
            Radix::Hexadecimal => 16,
        }
    }

    /// Get the radix prefix.
    pub fn as_prefix(&self) -> String {
        match self {
            Radix::Binary => String::from("0b"),
            Radix::Octal => String::from("0o"),
            Radix::Decimal => String::from(""),
            Radix::Hexadecimal => String::from("0x"),
        }
    }

    /// Return a closure that can be used to determine if a given character is a legal
    /// digit in the chosen radix.
    pub fn digit_test(&self) -> Box<dyn Fn(char) -> bool> {
        match self {
            Radix::Binary => Box::new(|ch| ch == '0' || ch == '1'),
            Radix::Octal => Box::new(|ch| ('0'..='7').contains(&ch)),
            Radix::Decimal => Box::new(|ch| char::is_ascii_digit(&ch)),
            Radix::Hexadecimal => Box::new(|ch| char::is_ascii_hexdigit(&ch)),
        }
    }
}

impl Debug for Radix {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "Radix::{}",
            match self {
                Radix::Binary => "Binary",
                Radix::Octal => "Octal",
                Radix::Decimal => "Decimal",
                Radix::Hexadecimal => "Hexadecimal",
            }
        )
    }
}

impl Display for Radix {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "{}",
            match self {
                Radix::Binary => "Binary",
                Radix::Octal => "Octal",
                Radix::Decimal => "Decimal",
                Radix::Hexadecimal => "Hexadecimal",
            }
        )
    }
}

#[cfg(test)]
mod test {
    use crate::numbers::Radix;

    #[test]
    fn value_test() {
        let mut radix = Radix::Binary;
        assert_eq!(radix.value(), 2);
        assert_eq!(radix.as_prefix(), "0b".to_string());
        assert!(!(radix.digit_test())('/'));
        assert!((radix.digit_test())('0'));
        assert!((radix.digit_test())('1'));
        assert!(!(radix.digit_test())('2'));
        assert!(!(radix.digit_test())('A'));
        assert!(!(radix.digit_test())('a'));

        radix = Radix::Octal;
        assert_eq!(radix.value(), 8);
        assert_eq!(radix.as_prefix(), "0o".to_string());
        assert!(!(radix.digit_test())('/'));
        assert!((radix.digit_test())('0'));
        assert!((radix.digit_test())('1'));
        assert!((radix.digit_test())('2'));
        assert!((radix.digit_test())('3'));
        assert!((radix.digit_test())('4'));
        assert!((radix.digit_test())('5'));
        assert!((radix.digit_test())('6'));
        assert!((radix.digit_test())('7'));
        assert!(!(radix.digit_test())('8'));
        assert!(!(radix.digit_test())('A'));
        assert!(!(radix.digit_test())('a'));

        radix = Radix::Decimal;
        assert_eq!(radix.value(), 10);
        assert_eq!(radix.as_prefix(), "".to_string());
        assert!(!(radix.digit_test())('/'));
        assert!((radix.digit_test())('0'));
        assert!((radix.digit_test())('1'));
        assert!((radix.digit_test())('2'));
        assert!((radix.digit_test())('3'));
        assert!((radix.digit_test())('4'));
        assert!((radix.digit_test())('5'));
        assert!((radix.digit_test())('6'));
        assert!((radix.digit_test())('7'));
        assert!((radix.digit_test())('8'));
        assert!((radix.digit_test())('9'));
        assert!(!(radix.digit_test())(':'));
        assert!(!(radix.digit_test())('A'));
        assert!(!(radix.digit_test())('a'));

        radix = Radix::Hexadecimal;
        assert_eq!(radix.value(), 16);
        assert_eq!(radix.as_prefix(), "0x".to_string());
        assert!(!(radix.digit_test())('/'));
        assert!((radix.digit_test())('0'));
        assert!((radix.digit_test())('1'));
        assert!((radix.digit_test())('2'));
        assert!((radix.digit_test())('3'));
        assert!((radix.digit_test())('4'));
        assert!((radix.digit_test())('5'));
        assert!((radix.digit_test())('6'));
        assert!((radix.digit_test())('7'));
        assert!((radix.digit_test())('8'));
        assert!((radix.digit_test())('9'));
        assert!(!(radix.digit_test())(':'));
        assert!(!(radix.digit_test())('@'));
        assert!(!(radix.digit_test())('`'));
        assert!((radix.digit_test())('A'));
        assert!((radix.digit_test())('a'));
        assert!((radix.digit_test())('B'));
        assert!((radix.digit_test())('b'));
        assert!((radix.digit_test())('C'));
        assert!((radix.digit_test())('c'));
        assert!((radix.digit_test())('D'));
        assert!((radix.digit_test())('d'));
        assert!((radix.digit_test())('E'));
        assert!((radix.digit_test())('e'));
        assert!((radix.digit_test())('F'));
        assert!((radix.digit_test())('f'));
        assert!(!(radix.digit_test())('G'));
        assert!(!(radix.digit_test())('g'));
    }
}