use std::str::FromStr;
use either::Either;
use unicase::Ascii;
use super::token68::Token68;
use crate::field::rules::{
flat_csv::{split_field_params, Comma},
parameters::FieldParameters,
token::Token,
};
#[derive(Debug, Clone)]
pub struct Challenge {
pub auth_scheme: Ascii<Token>,
pub ext_info: Either<Token68, FieldParameters<Comma>>,
}
impl FromStr for Challenge {
type Err = InvalidEncodedChallenge;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (auth_scheme_str, info_str) =
s.trim().split_once(' ').ok_or(InvalidEncodedChallenge)?;
let auth_scheme =
Ascii::new(Token::from_str(auth_scheme_str).map_err(|_| InvalidEncodedChallenge)?);
let ext_info = if let Ok(t) = Token68::from_str(info_str) {
Either::Left(t)
} else {
Either::Right(
FieldParameters::<Comma>::decode(split_field_params::<Comma>(info_str), false)
.map_err(|_| InvalidEncodedChallenge)?,
)
};
Ok(Self {
auth_scheme,
ext_info,
})
}
}
impl Challenge {
pub fn encode(&self) -> String {
let mut buf = String::new();
buf.push_str(self.auth_scheme.as_ref());
buf.push(' ');
match &self.ext_info {
Either::Left(t) => buf.push_str(t.as_str()),
Either::Right(ps) => ps.push_encoded_str(&mut buf),
}
buf
}
}
#[derive(Debug, thiserror::Error)]
#[error("Invalid encoded challenge.")]
pub struct InvalidEncodedChallenge;