use std::fmt::{Debug, Display, Formatter};
use bimap::BiHashMap;
use guppy::PackageId;
use crate::Type;
use crate::named_lifetime::NamedLifetime;
use crate::render::{LifetimeStyle, PathStyle, RenderConfig};
#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Clone)]
pub enum GenericArgument {
TypeParameter(Type),
Lifetime(GenericLifetimeParameter),
Const(ConstGenericArgument),
}
#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Clone)]
pub struct ConstGenericArgument {
pub value: String,
}
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, Clone)]
pub enum GenericLifetimeParameter {
Named(NamedLifetime),
Static,
Inferred,
}
impl GenericLifetimeParameter {
pub fn from_name(name: impl Into<String>) -> Self {
let mut name = name.into();
if let Some(stripped) = name.strip_prefix('\'') {
name = stripped.to_owned();
}
match name.as_str() {
"_" => GenericLifetimeParameter::Inferred,
"static" => GenericLifetimeParameter::Static,
_ => GenericLifetimeParameter::Named(NamedLifetime::new(name)),
}
}
}
impl GenericArgument {
pub fn render_type_into(&self, id2name: &BiHashMap<PackageId, String>, buffer: &mut String) {
let config = RenderConfig {
path: PathStyle::CrateLookup(id2name),
lifetime: LifetimeStyle::Preserve,
};
self.render_into(&config, buffer);
}
pub fn render_with_inferred_lifetimes_into(
&self,
id2name: &BiHashMap<PackageId, String>,
buffer: &mut String,
) {
let config = RenderConfig {
path: PathStyle::CrateLookup(id2name),
lifetime: LifetimeStyle::Erase,
};
self.render_into(&config, buffer);
}
pub fn display_for_error_into<W: std::fmt::Write>(&self, buffer: &mut W) {
let config = RenderConfig {
path: PathStyle::Direct,
lifetime: LifetimeStyle::Preserve,
};
self.render_into(&config, buffer);
}
pub(crate) fn render_into<W: std::fmt::Write>(
&self,
config: &RenderConfig<'_>,
buffer: &mut W,
) {
match self {
GenericArgument::TypeParameter(t) => {
t.render_into(config, buffer);
}
GenericArgument::Lifetime(l) => match config.lifetime {
LifetimeStyle::Preserve => {
write!(buffer, "{l}").unwrap();
}
LifetimeStyle::Erase => match l {
GenericLifetimeParameter::Static => {
write!(buffer, "'static").unwrap();
}
GenericLifetimeParameter::Named(_) | GenericLifetimeParameter::Inferred => {
write!(buffer, "'_").unwrap();
}
},
},
GenericArgument::Const(c) => {
write!(buffer, "{}", c.value).unwrap();
}
}
}
}
impl Display for GenericLifetimeParameter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GenericLifetimeParameter::Named(l) => write!(f, "'{l}"),
GenericLifetimeParameter::Static => write!(f, "'static"),
GenericLifetimeParameter::Inferred => write!(f, "'_"),
}
}
}
impl Display for GenericArgument {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GenericArgument::TypeParameter(t) => write!(f, "{t}"),
GenericArgument::Lifetime(l) => write!(f, "{l}"),
GenericArgument::Const(c) => write!(f, "{}", c.value),
}
}
}
impl Debug for GenericArgument {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GenericArgument::TypeParameter(r) => write!(f, "{r:?}"),
GenericArgument::Lifetime(l) => write!(f, "{l:?}"),
GenericArgument::Const(c) => write!(f, "{}", c.value),
}
}
}
impl Debug for GenericLifetimeParameter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GenericLifetimeParameter::Named(name) => write!(f, "'{name}"),
GenericLifetimeParameter::Static => write!(f, "'static"),
GenericLifetimeParameter::Inferred => write!(f, "'_"),
}
}
}