use std::fmt;
use std::str::FromStr;
use crate::errors::ParamParseError;
use crate::tl::{Flag, Type};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ParameterType {
Flags,
Normal {
ty: Type,
flag: Option<Flag>,
},
}
impl fmt::Display for ParameterType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Flags => write!(f, "#"),
Self::Normal { ty, flag } => {
if let Some(fl) = flag {
write!(f, "{}.{}?", fl.name, fl.index)?;
}
write!(f, "{ty}")
}
}
}
}
impl FromStr for ParameterType {
type Err = ParamParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "#" {
return Ok(Self::Flags);
}
if let Some((flag_part, ty_part)) = s.split_once('?') {
let (flag_name, flag_idx) = flag_part
.split_once('.')
.ok_or(ParamParseError::InvalidFlag)?;
if flag_name.is_empty() || flag_idx.is_empty() {
return Err(ParamParseError::InvalidFlag);
}
let index = flag_idx
.parse::<u32>()
.map_err(|_| ParamParseError::InvalidFlag)?;
let ty = Type::from_str(ty_part)?;
return Ok(Self::Normal {
ty,
flag: Some(Flag {
name: flag_name.to_owned(),
index,
}),
});
}
if s.contains('?') {
return Err(ParamParseError::InvalidFlag);
}
Ok(Self::Normal {
ty: Type::from_str(s)?,
flag: None,
})
}
}