use std::collections::HashMap;
use syn::{
ext::IdentExt,
parse::{Parse, ParseStream},
Ident, Type,
};
pub(super) struct TypeOverride {
type_name: Ident,
field_name: Ident,
arg_name: Option<Ident>,
type_ident: Type,
}
impl TypeOverride {
pub(crate) fn type_name(&self) -> &Ident {
&self.type_name
}
pub(crate) fn field_name(&self) -> &Ident {
&self.field_name
}
pub(crate) fn arg_name(&self) -> Option<&Ident> {
self.arg_name.as_ref()
}
pub(super) fn type_ident(self) -> Type {
self.type_ident
}
}
impl Parse for TypeOverride {
fn parse(input: ParseStream) -> syn::Result<Self> {
let type_name = input.call(Ident::parse_any)?;
_ = input.parse::<syn::Token![.]>()?;
let field_name = input.call(Ident::parse_any)?;
let arg_name = if input.peek(syn::Token![.]) {
_ = input.parse::<syn::Token![.]>()?;
Some(input.call(Ident::parse_any)?)
} else {
None
};
_ = input.parse::<syn::Token![:]>()?;
let type_ident = input
.parse()
.map_err(|e| syn::Error::new(e.span(), "Expected a Type (struct, enum, etc...)"))?;
Ok(Self {
type_name,
field_name,
arg_name,
type_ident,
})
}
}
pub(super) struct NameOverride {
type_name: Ident,
field_name: Option<Ident>,
new_name: String,
}
impl NameOverride {
pub(crate) fn type_name(&self) -> &Ident {
&self.type_name
}
pub(crate) fn field_name(&self) -> Option<&Ident> {
self.field_name.as_ref()
}
pub(super) fn new_name(self) -> String {
self.new_name
}
}
impl Parse for NameOverride {
fn parse(input: ParseStream) -> syn::Result<Self> {
let type_name = input.call(Ident::parse_any)?;
let field_name = if input.peek(syn::Token![.]) {
_ = input.parse::<syn::Token![.]>()?;
Some(input.call(Ident::parse_any)?)
} else {
None
};
_ = input.parse::<syn::Token![:]>()?;
let new_name = input.call(Ident::parse_any)?;
let new_name = new_name.to_string();
Ok(Self {
type_name,
field_name,
new_name,
})
}
}
pub(crate) type TypeOverrides = HashMap<TypeName, FieldTypeOverrides>;
pub(crate) type FieldTypeOverrides = HashMap<FieldName, FieldTypeOverride>;
pub(crate) type FieldTypeOverride = (Option<TypeOverride>, ArgTypeOverrides);
pub(crate) type ArgTypeOverrides = HashMap<ArgName, TypeOverride>;
pub(crate) type NameOverrides = HashMap<TypeName, TypeNameOverride>;
pub(crate) type TypeNameOverride = (Option<NameOverride>, FieldNameOverrides);
pub(crate) type FieldNameOverrides = HashMap<FieldName, NameOverride>;
pub(crate) type TypeName = String;
pub(crate) type FieldName = String;
pub(crate) type ArgName = String;
use super::optional_parameter::{OptionalParameter, OptionalParameters, ParameterError, Unknown};
pub(super) enum OverrideParameter {
TypeOverride(TypeOverride),
NameOverride(NameOverride),
}
impl OptionalParameter for OverrideParameter {
fn try_parse_parameter(input: ParseStream) -> Result<Self, ParameterError> {
let ident = Self::parse_ident(input)?;
match ident.to_string().as_str() {
"type_override" => Ok(Self::TypeOverride(input.parse()?)),
"name_override" => Ok(Self::NameOverride(input.parse()?)),
_ => ident.unknown(),
}
}
}
#[derive(Default)]
pub(super) struct OverrideParameters {
pub type_overrides: TypeOverrides,
pub name_overrides: NameOverrides,
}
impl OptionalParameters<OverrideParameter> for OverrideParameters {
fn set_param(&mut self, p: OverrideParameter) {
match p {
OverrideParameter::TypeOverride(to) => {
let to_field_entry = self
.type_overrides
.entry(to.type_name().to_string())
.or_default()
.entry(to.field_name().to_string())
.or_default();
if let Some(arg_name) = to.arg_name() {
to_field_entry.1.insert(arg_name.to_string(), to);
} else {
to_field_entry.0.replace(to);
}
}
OverrideParameter::NameOverride(no) => {
let no_type_entry = self
.name_overrides
.entry(no.type_name().to_string())
.or_default();
if let Some(field_name) = no.field_name() {
no_type_entry.1.insert(field_name.to_string(), no);
} else {
no_type_entry.0.replace(no);
}
}
}
}
}