use std::fmt;
use std::str::FromStr;
use crate::errors::ParamParseError;
use crate::tl::Type;
#[derive(Debug, PartialEq)]
pub struct Parameter {
pub name: String,
pub ty: Type,
pub description: String,
}
impl fmt::Display for Parameter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.name, self.ty)
}
}
impl FromStr for Parameter {
type Err = ParamParseError;
fn from_str(param: &str) -> Result<Self, Self::Err> {
let (name, ty) = {
let mut it = param.split(':');
if let Some(n) = it.next() {
if let Some(t) = it.next() {
(n, t)
} else {
return Err(ParamParseError::NotImplemented);
}
} else {
return Err(ParamParseError::Empty);
}
};
if name.is_empty() {
return Err(ParamParseError::Empty);
}
Ok(Parameter {
name: name.into(),
ty: ty.parse()?,
description: String::new(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tl::Type;
#[test]
fn parse_empty_param() {
assert_eq!(Parameter::from_str(":noname"), Err(ParamParseError::Empty));
assert_eq!(Parameter::from_str("notype:"), Err(ParamParseError::Empty));
assert_eq!(Parameter::from_str(":"), Err(ParamParseError::Empty));
}
#[test]
fn parse_unknown_param() {
assert_eq!(
Parameter::from_str(""),
Err(ParamParseError::NotImplemented)
);
assert_eq!(
Parameter::from_str("no colon"),
Err(ParamParseError::NotImplemented)
);
assert_eq!(
Parameter::from_str("colonless"),
Err(ParamParseError::NotImplemented)
);
}
#[test]
fn parse_bad_generics() {
assert_eq!(
Parameter::from_str("foo:<bar"),
Err(ParamParseError::InvalidGeneric)
);
assert_eq!(
Parameter::from_str("foo:bar<"),
Err(ParamParseError::InvalidGeneric)
);
}
#[test]
fn parse_valid_param() {
assert_eq!(
Parameter::from_str("foo:bar<baz>"),
Ok(Parameter {
name: "foo".into(),
ty: Type {
name: "bar".into(),
bare: true,
generic_arg: Some(Box::new("baz".parse().unwrap())),
},
description: String::new(),
})
);
}
}