refinement_types/char/
ascii.rs

1//! ASCII character predicates.
2
3use core::{fmt, marker::PhantomData};
4
5#[cfg(feature = "diagnostics")]
6use miette::Diagnostic;
7
8use thiserror::Error;
9
10use crate::{char::macros::predicate, core::Predicate};
11
12/// Represents integer base for checks.
13pub type Base = u32;
14
15/// Non-digit character encountered in the given [`base`].
16///
17/// [`base`]: Self::base
18#[derive(Debug, Error)]
19#[error("non-digit character in base `{base}`")]
20#[cfg_attr(
21    feature = "diagnostics",
22    derive(Diagnostic),
23    diagnostic(
24        code(char::digit),
25        help("make sure the character is base `{base}` digit")
26    )
27)]
28pub struct DigitError {
29    /// The base in which the non-digit character was encountered.
30    pub base: Base,
31}
32
33impl DigitError {
34    /// Constructs [`Self`].
35    #[must_use]
36    pub const fn new(base: Base) -> Self {
37        Self { base }
38    }
39}
40
41/// Checks whether the given character is a digit in the specified base `B`.
42pub struct Digit<const B: Base = 10> {
43    private: PhantomData<()>,
44}
45
46/// Checks whether the given character is an octal digit.
47pub type OctDigit = Digit<8>;
48
49/// Checks whether the given character is a hexadecimal digit.
50pub type HexDigit = Digit<16>;
51
52impl<const B: Base> Predicate<char> for Digit<B> {
53    type Error = DigitError;
54
55    fn check(value: &char) -> Result<(), Self::Error> {
56        if value.is_digit(B) {
57            Ok(())
58        } else {
59            Err(Self::Error::new(B))
60        }
61    }
62
63    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(formatter, "digit in base {B}")
65    }
66
67    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
68        write!(formatter, "char::digit<{B}>")
69    }
70}
71
72predicate! {
73    Name = Alphabetic,
74    Check = is_ascii_alphabetic,
75    Doc = "Checks whether the given character is ASCII alphabetic.",
76    Expected = "ascii alphabetic character",
77    Code = char::ascii::alphabetic,
78    Error = "Non-ASCII-alphabetic character encountered.",
79    Message = "non-ascii-alphabetic character",
80    Help = "make sure the character is ascii alphabetic",
81}
82
83predicate! {
84    Name = Alphanumeric,
85    Check = is_ascii_alphanumeric,
86    Doc = "Checks whether the given character is ASCII alphanumeric.",
87    Expected = "ascii alphanumeric character",
88    Code = char::ascii::alphanumeric,
89    Error = "Non-ASCII-alphanumeric character encountered.",
90    Message = "non-ascii-alphanumeric character",
91    Help = "make sure the character is ascii alphanumeric",
92}
93
94predicate! {
95    Name = Control,
96    Check = is_ascii_control,
97    Doc = "Checks whether the given character is ASCII control.",
98    Expected = "ascii control character",
99    Code = char::ascii::control,
100    Error = "Non-ASCII-control character encountered.",
101    Message = "non-ascii-control character",
102    Help = "make sure the character is ascii control",
103}
104
105predicate! {
106    Name = Graphic,
107    Check = is_ascii_graphic,
108    Doc = "Checks whether the given character is ASCII graphic.",
109    Expected = "ascii graphic character",
110    Code = char::ascii::graphic,
111    Error = "Non-ASCII-graphic character encountered.",
112    Message = "non-ascii-graphic character",
113    Help = "make sure the character is ascii graphic",
114}
115
116predicate! {
117    Name = Punctuation,
118    Check = is_ascii_punctuation,
119    Doc = "Checks whether the given character is ASCII punctuation.",
120    Expected = "ascii punctuation character",
121    Code = char::ascii::punctuation,
122    Error = "Non-ASCII-punctuation character encountered.",
123    Message = "non-ascii-punctuation character",
124    Help = "make sure the character is ascii punctuation",
125}
126
127predicate! {
128    Name = Lowercase,
129    Check = is_ascii_lowercase,
130    Doc = "Checks whether the given character is ASCII lowercase.",
131    Expected = "ascii lowercase character",
132    Code = char::ascii::lowercase,
133    Error = "Non-ASCII-lowercase character encountered.",
134    Message = "non-ascii-lowercase character",
135    Help = "make sure the character is ascii lowercase",
136}
137
138predicate! {
139    Name = Uppercase,
140    Check = is_ascii_uppercase,
141    Doc = "Checks whether the given character is ASCII uppercase.",
142    Expected = "ascii uppercase character",
143    Code = char::ascii::uppercase,
144    Error = "Non-ASCII-uppercase character encountered.",
145    Message = "non-ascii-uppercase character",
146    Help = "make sure the character is ascii uppercase",
147}
148
149predicate! {
150    Name = Whitespace,
151    Check = is_ascii_whitespace,
152    Doc = "Checks whether the given character is ASCII whitespace.",
153    Expected = "ascii whitespace character",
154    Code = char::ascii::whitespace,
155    Error = "Non-ASCII-whitespace character encountered.",
156    Message = "non-ascii-whitespace character",
157    Help = "make sure the character is ascii whitespace",
158}