use std::str::FromStr;
#[cfg(feature = "diagnostics")]
use miette::Diagnostic;
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use thiserror::Error;
#[derive(Debug, Error)]
#[error("unknown method `{unknown}`")]
#[cfg_attr(
feature = "diagnostics",
derive(Diagnostic),
diagnostic(
code(pkce_std::method),
help("expected either `{PLAIN}` (discouraged) or `{SHA256}` (recommended)")
)
)]
pub struct Error {
pub unknown: String,
}
impl Error {
pub const fn new(unknown: String) -> Self {
Self { unknown }
}
}
pub const PLAIN: &str = "plain";
pub const SHA256: &str = "S256";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Method {
Plain,
#[default]
Sha256,
}
#[cfg(feature = "serde")]
impl Serialize for Method {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.static_str().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Method {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let string = <&str>::deserialize(deserializer)?;
string.parse().map_err(de::Error::custom)
}
}
type StaticStr = &'static str;
impl Method {
pub const fn static_str(&self) -> StaticStr {
match self {
Self::Plain => PLAIN,
Self::Sha256 => SHA256,
}
}
}
impl FromStr for Method {
type Err = Error;
fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
PLAIN => Ok(Self::Plain),
SHA256 => Ok(Self::Sha256),
_ => Err(Self::Err::new(string.to_owned())),
}
}
}