pkce_std/check/
bytes.rs

1//! Checking PKCE code verifiers using bytes instead of characters.
2
3use const_macros::const_early;
4
5#[cfg(feature = "diagnostics")]
6use miette::Diagnostic;
7
8use thiserror::Error;
9
10/// Represents errors that occur when invalid bytes are encountered.
11#[derive(Debug, Error)]
12#[error("invalid byte `{byte}` encountered")]
13#[cfg_attr(
14    feature = "diagnostics",
15    derive(Diagnostic),
16    diagnostic(code(pkce_std::check::bytes), help("ensure the byte is valid"))
17)]
18pub struct Error {
19    /// The invalid byte.
20    pub byte: u8,
21}
22
23impl Error {
24    /// Constructs [`Self`].
25    pub const fn new(byte: u8) -> Self {
26        Self { byte }
27    }
28}
29
30macro_rules! special_pattern {
31    () => {
32        b'-' | b'.' | b'_' | b'~'
33    };
34}
35
36/// Checks if the given byte is special, i.e. one of `-`, `.`, `_`, or `~`.
37pub const fn is_special(byte: u8) -> bool {
38    matches!(byte, special_pattern!())
39}
40
41/// Checks if the given byte is valid, i.e. either alphanumeric or special.
42pub const fn is_valid(byte: u8) -> bool {
43    byte.is_ascii_alphanumeric() || is_special(byte)
44}
45
46/// Checks that the given byte is valid.
47///
48/// # Examples
49///
50/// ```
51/// use pkce_std::check::bytes::check;
52///
53/// let minus = b'-';
54/// let plus = b'+';
55///
56/// assert!(check(minus).is_ok());
57/// assert!(check(plus).is_err());
58/// ```
59///
60/// # Errors
61///
62/// Returns [`struct@Error`] if the byte is invalid.
63pub const fn check(byte: u8) -> Result<(), Error> {
64    const_early!(!is_valid(byte) => Error::new(byte));
65
66    Ok(())
67}