use crate::parser::str::find_split_hole;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct Literal<'a>(&'a str);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct VarName<'a>(&'a str);
impl<'a> VarName<'a> {
#[inline]
#[must_use]
pub(super) fn new(s: &'a str) -> Self {
Self(s)
}
#[inline]
#[must_use]
pub(super) fn as_str(&self) -> &'a str {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct VarSpec<'a> {
name: VarName<'a>,
modifier: Modifier,
}
impl<'a> VarSpec<'a> {
#[inline]
#[must_use]
pub(super) fn name(&self) -> VarName<'a> {
self.name
}
#[inline]
#[must_use]
pub(super) fn modifier(&self) -> Modifier {
self.modifier
}
#[must_use]
pub(super) fn parse_trusted(s: &'a str) -> Self {
if let Some(varname) = s.strip_suffix('*') {
return Self {
name: VarName::new(varname),
modifier: Modifier::Explode,
};
}
match find_split_hole(s, b':') {
Some((varname, max_len)) => {
let max_len: u16 = max_len
.parse()
.expect("[precondition] the input should be valid `varspec`");
Self {
name: VarName::new(varname),
modifier: Modifier::MaxLen(max_len),
}
}
None => Self {
name: VarName(s),
modifier: Modifier::None,
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum Modifier {
None,
MaxLen(u16),
Explode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct VarList<'a>(&'a [VarSpec<'a>]);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum MaybeOperator {
Operator(Operator),
Reserved(OperatorReservedForFuture),
}
impl MaybeOperator {
pub(super) fn from_byte(b: u8) -> Option<Self> {
match b {
b'+' => Some(Self::Operator(Operator::Reserved)),
b'#' => Some(Self::Operator(Operator::Fragment)),
b'.' => Some(Self::Operator(Operator::Label)),
b'/' => Some(Self::Operator(Operator::PathSegments)),
b';' => Some(Self::Operator(Operator::PathParams)),
b'?' => Some(Self::Operator(Operator::FormQuery)),
b'&' => Some(Self::Operator(Operator::FormQueryCont)),
b'=' => Some(Self::Reserved(OperatorReservedForFuture::Equals)),
b',' => Some(Self::Reserved(OperatorReservedForFuture::Comma)),
b'!' => Some(Self::Reserved(OperatorReservedForFuture::Exclamation)),
b'@' => Some(Self::Reserved(OperatorReservedForFuture::AtSign)),
b'|' => Some(Self::Reserved(OperatorReservedForFuture::Pipe)),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum Operator {
String,
Reserved,
Fragment,
Label,
PathSegments,
PathParams,
FormQuery,
FormQueryCont,
}
impl Operator {
#[must_use]
pub(super) fn from_byte(b: u8) -> Option<Self> {
match b {
b'+' => Some(Self::Reserved),
b'#' => Some(Self::Fragment),
b'.' => Some(Self::Label),
b'/' => Some(Self::PathSegments),
b';' => Some(Self::PathParams),
b'?' => Some(Self::FormQuery),
b'&' => Some(Self::FormQueryCont),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum OperatorReservedForFuture {
Equals,
Comma,
Exclamation,
AtSign,
Pipe,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct Expression<'a> {
operator: Operator,
variables: VarList<'a>,
}