refinement_types/char/
ascii.rs

1//! ASCII character predicates.
2
3use core::fmt;
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`.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
43pub struct Digit<const B: Base = 10>;
44
45/// Checks whether the given character is an octal digit.
46pub type OctDigit = Digit<8>;
47
48/// Checks whether the given character is a hexadecimal digit.
49pub type HexDigit = Digit<16>;
50
51impl<const B: Base> Predicate<char> for Digit<B> {
52    type Error = DigitError;
53
54    fn check(value: &char) -> Result<(), Self::Error> {
55        if value.is_digit(B) {
56            Ok(())
57        } else {
58            Err(Self::Error::new(B))
59        }
60    }
61
62    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(formatter, "digit in base {B}")
64    }
65
66    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
67        write!(formatter, "char::digit<{B}>")
68    }
69}
70
71predicate! {
72    Name = Alphabetic,
73    Check = is_ascii_alphabetic,
74    Doc = "Checks whether the given character is ASCII alphabetic.",
75    Expected = "ascii alphabetic character",
76    Code = char::ascii::alphabetic,
77    Error = "Non-ASCII-alphabetic character encountered.",
78    Message = "non-ascii-alphabetic character",
79    Help = "make sure the character is ascii alphabetic",
80}
81
82predicate! {
83    Name = Alphanumeric,
84    Check = is_ascii_alphanumeric,
85    Doc = "Checks whether the given character is ASCII alphanumeric.",
86    Expected = "ascii alphanumeric character",
87    Code = char::ascii::alphanumeric,
88    Error = "Non-ASCII-alphanumeric character encountered.",
89    Message = "non-ascii-alphanumeric character",
90    Help = "make sure the character is ascii alphanumeric",
91}
92
93predicate! {
94    Name = Control,
95    Check = is_ascii_control,
96    Doc = "Checks whether the given character is ASCII control.",
97    Expected = "ascii control character",
98    Code = char::ascii::control,
99    Error = "Non-ASCII-control character encountered.",
100    Message = "non-ascii-control character",
101    Help = "make sure the character is ascii control",
102}
103
104predicate! {
105    Name = Graphic,
106    Check = is_ascii_graphic,
107    Doc = "Checks whether the given character is ASCII graphic.",
108    Expected = "ascii graphic character",
109    Code = char::ascii::graphic,
110    Error = "Non-ASCII-graphic character encountered.",
111    Message = "non-ascii-graphic character",
112    Help = "make sure the character is ascii graphic",
113}
114
115predicate! {
116    Name = Punctuation,
117    Check = is_ascii_punctuation,
118    Doc = "Checks whether the given character is ASCII punctuation.",
119    Expected = "ascii punctuation character",
120    Code = char::ascii::punctuation,
121    Error = "Non-ASCII-punctuation character encountered.",
122    Message = "non-ascii-punctuation character",
123    Help = "make sure the character is ascii punctuation",
124}
125
126predicate! {
127    Name = Lowercase,
128    Check = is_ascii_lowercase,
129    Doc = "Checks whether the given character is ASCII lowercase.",
130    Expected = "ascii lowercase character",
131    Code = char::ascii::lowercase,
132    Error = "Non-ASCII-lowercase character encountered.",
133    Message = "non-ascii-lowercase character",
134    Help = "make sure the character is ascii lowercase",
135}
136
137predicate! {
138    Name = Uppercase,
139    Check = is_ascii_uppercase,
140    Doc = "Checks whether the given character is ASCII uppercase.",
141    Expected = "ascii uppercase character",
142    Code = char::ascii::uppercase,
143    Error = "Non-ASCII-uppercase character encountered.",
144    Message = "non-ascii-uppercase character",
145    Help = "make sure the character is ascii uppercase",
146}
147
148predicate! {
149    Name = Whitespace,
150    Check = is_ascii_whitespace,
151    Doc = "Checks whether the given character is ASCII whitespace.",
152    Expected = "ascii whitespace character",
153    Code = char::ascii::whitespace,
154    Error = "Non-ASCII-whitespace character encountered.",
155    Message = "non-ascii-whitespace character",
156    Help = "make sure the character is ascii whitespace",
157}