1use const_macros::const_early;
4
5#[cfg(feature = "diagnostics")]
6use miette::Diagnostic;
7
8use thiserror::Error;
9
10#[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 pub byte: u8,
21}
22
23impl Error {
24 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
36pub const fn is_special(byte: u8) -> bool {
38 matches!(byte, special_pattern!())
39}
40
41pub const fn is_valid(byte: u8) -> bool {
43 byte.is_ascii_alphanumeric() || is_special(byte)
44}
45
46pub const fn check(byte: u8) -> Result<(), Error> {
64 const_early!(!is_valid(byte) => Error::new(byte));
65
66 Ok(())
67}