use const_macros::{const_map_err, const_try};
#[cfg(feature = "diagnostics")]
use miette::Diagnostic;
use thiserror::Error;
use crate::check::{ascii, bytes};
#[derive(Debug, Error)]
#[error("invalid string encountered")]
#[cfg_attr(feature = "diagnostics", derive(Diagnostic))]
pub enum Error {
#[cfg_attr(
feature = "diagnostics",
diagnostic(
code(pkce_std::check::string::ascii),
help("ensure the string is ASCII")
)
)]
Ascii(#[from] ascii::Error),
#[cfg_attr(
feature = "diagnostics",
diagnostic(code(pkce_std::check::string::byte), help("ensure the byte is valid"))
)]
Bytes(#[from] bytes::Error),
}
pub const fn const_check_str(string: &str) -> Result<(), Error> {
pub const fn check_bytes(bytes: &[u8]) -> Result<(), bytes::Error> {
match *bytes {
[] => Ok(()),
[byte, ref rest @ ..] => {
const_try!(bytes::check(byte));
check_bytes(rest)
}
}
}
const_try!(const_map_err!(ascii::check_str(string) => Error::Ascii));
const_map_err!(check_bytes(string.as_bytes()) => Error::Bytes)
}
pub fn check_str(string: &str) -> Result<(), Error> {
fn check_bytes(bytes: &[u8]) -> Result<(), bytes::Error> {
bytes.iter().copied().try_for_each(bytes::check)
}
ascii::check(string)?;
check_bytes(string.as_bytes())?;
Ok(())
}
pub fn check<S: AsRef<str>>(string: S) -> Result<(), Error> {
check_str(string.as_ref())
}