use std::fmt::{self, Write};
use crate::formatter::Formatter;
#[derive(Debug, Clone)]
pub struct Type {
name: String,
generics: Vec<Type>,
}
impl Type {
pub fn new(name: impl Into<String>) -> Self {
Type {
name: name.into(),
generics: vec![],
}
}
pub fn generic<T>(&mut self, ty: T) -> &mut Self
where
T: Into<Type>,
{
assert!(
!self.name.contains("<"),
"type name already includes generics"
);
self.generics.push(ty.into());
self
}
pub fn path(&self, path: &str) -> Type {
assert!(!self.name.contains("::"));
let mut name = path.to_string();
name.push_str("::");
name.push_str(&self.name);
Type {
name,
generics: self.generics.clone(),
}
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "{}", self.name)?;
Type::fmt_slice(&self.generics, fmt)
}
fn fmt_slice(generics: &[Type], fmt: &mut Formatter<'_>) -> fmt::Result {
if !generics.is_empty() {
write!(fmt, "<")?;
for (i, ty) in generics.iter().enumerate() {
if i != 0 {
write!(fmt, ", ")?
}
ty.fmt(fmt)?;
}
write!(fmt, ">")?;
}
Ok(())
}
}
impl<S: Into<String>> From<S> for Type {
fn from(src: S) -> Self {
Type {
name: src.into(),
generics: vec![],
}
}
}
impl<'a> From<&'a Type> for Type {
fn from(src: &'a Type) -> Self {
src.clone()
}
}