use std::any::Any;
use std::fmt::{Debug, Display};
use std::mem::take;
use proc_macro2::Ident as Ident2;
use quote::format_ident;
use crate::models::{
meta::{MetaType, MetaTypes},
schema::NamespaceId,
Name, TypeIdent,
};
pub trait Naming: Debug {
fn clone_boxed(&self) -> Box<dyn Naming>;
fn builder(&self) -> Box<dyn NameBuilder>;
fn unify(&self, s: &str) -> String;
fn make_type_name(&self, postfixes: &[String], ty: &MetaType, ident: &TypeIdent) -> Name;
fn make_unknown_variant(&self, id: usize) -> Ident2;
fn format_module_name(&self, s: &str) -> String;
fn format_type_name(&self, s: &str) -> String;
fn format_field_name(&self, s: &str) -> String;
fn format_variant_name(&self, s: &str) -> String;
fn format_constant_name(&self, s: &str) -> String;
fn format_attribute_field_name(&self, s: &str) -> String {
self.format_field_name(s)
}
fn format_element_field_name(&self, s: &str) -> String {
self.format_field_name(s)
}
fn format_module_ident(&self, name: &Name) -> Ident2 {
let ident = self.format_module_name(name.as_str());
format_ident!("{ident}")
}
fn format_type_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_type_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_field_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_variant_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_variant_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_constant_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_constant_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_attribute_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_attribute_field_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_element_field_ident(&self, name: &Name, display_name: Option<&str>) -> Ident2 {
let ident = self.format_element_field_name(display_name.unwrap_or(name.as_str()));
format_ident!("{ident}")
}
fn format_module(&self, types: &MetaTypes, ns: Option<NamespaceId>) -> Option<Ident2> {
let ns = ns?;
let module = types.modules.get(&ns)?;
let name = module.name.as_ref()?;
Some(self.format_module_ident(name))
}
}
pub trait NameBuilder: Debug + Any {
fn finish(&self) -> Name;
fn merge(&mut self, other: &dyn NameBuilder);
fn clone_boxed(&self) -> Box<dyn NameBuilder>;
fn has_name(&self) -> bool;
fn has_extension(&self) -> bool;
fn set_name(&mut self, name: String);
fn set_with_id(&mut self, value: bool);
fn set_generated(&mut self, value: bool);
fn add_extension(&mut self, replace: bool, extension: String);
fn strip_suffix(&mut self, suffix: &str);
fn generate_unique_id(&mut self);
fn prepare_type_name(&mut self);
fn prepare_field_name(&mut self);
fn prepare_content_type_name(&mut self);
}
impl NameBuilder for Box<dyn NameBuilder> {
#[inline]
fn finish(&self) -> Name {
(**self).finish()
}
#[inline]
fn merge(&mut self, other: &dyn NameBuilder) {
(**self).merge(other);
}
#[inline]
fn clone_boxed(&self) -> Box<dyn NameBuilder> {
(**self).clone_boxed()
}
#[inline]
fn has_name(&self) -> bool {
(**self).has_name()
}
#[inline]
fn has_extension(&self) -> bool {
(**self).has_extension()
}
#[inline]
fn set_name(&mut self, name: String) {
(**self).set_name(name);
}
#[inline]
fn set_with_id(&mut self, value: bool) {
(**self).set_with_id(value);
}
#[inline]
fn set_generated(&mut self, value: bool) {
(**self).set_generated(value);
}
#[inline]
fn add_extension(&mut self, replace: bool, extension: String) {
(**self).add_extension(replace, extension);
}
#[inline]
fn strip_suffix(&mut self, suffix: &str) {
(**self).strip_suffix(suffix);
}
#[inline]
fn generate_unique_id(&mut self) {
(**self).generate_unique_id();
}
#[inline]
fn prepare_type_name(&mut self) {
(**self).prepare_type_name();
}
#[inline]
fn prepare_field_name(&mut self) {
(**self).prepare_field_name();
}
#[inline]
fn prepare_content_type_name(&mut self) {
(**self).prepare_content_type_name();
}
}
pub trait NameBuilderExt: Sized {
#[must_use]
fn generate_id(self) -> Self;
#[must_use]
fn with_id(self, value: bool) -> Self;
#[must_use]
fn extend<I>(self, replace: bool, iter: I) -> Self
where
I: IntoIterator,
I::Item: Display;
#[must_use]
fn remove_suffix(self, suffix: &str) -> Self;
#[must_use]
fn unique_name<T>(self, value: T) -> Self
where
T: Display;
#[must_use]
fn shared_name<T>(self, value: T) -> Self
where
T: Display;
#[must_use]
fn or<T>(self, fallback: T) -> Self
where
T: NameFallback;
#[must_use]
fn or_else<F, T>(self, fallback: F) -> Self
where
F: FnOnce() -> T,
T: NameFallback;
#[must_use]
fn type_name(self) -> Self;
#[must_use]
fn field_name(self) -> Self;
#[must_use]
fn content_type_name(self) -> Self;
}
impl<X> NameBuilderExt for X
where
X: NameBuilder + Sized,
{
fn generate_id(mut self) -> Self {
self.generate_unique_id();
self
}
fn with_id(mut self, value: bool) -> Self {
self.set_with_id(value);
self
}
fn extend<I>(mut self, mut replace: bool, iter: I) -> Self
where
I: IntoIterator,
I::Item: Display,
{
for ext in iter {
let ext = ext.to_string();
self.add_extension(take(&mut replace), ext);
}
self
}
fn remove_suffix(mut self, suffix: &str) -> Self {
self.strip_suffix(suffix);
self
}
fn unique_name<T>(mut self, value: T) -> Self
where
T: Display,
{
self.set_name(value.to_string());
self.set_with_id(false);
self
}
fn shared_name<T>(mut self, value: T) -> Self
where
T: Display,
{
self.set_name(value.to_string());
self.set_with_id(true);
self
}
fn or<T>(self, fallback: T) -> Self
where
T: NameFallback,
{
self.or_else(|| fallback)
}
fn or_else<F, T>(mut self, fallback: F) -> Self
where
F: FnOnce() -> T,
T: NameFallback,
{
if !self.has_name() {
fallback().apply(&mut self);
}
self
}
fn type_name(mut self) -> Self {
self.prepare_type_name();
self
}
fn field_name(mut self) -> Self {
self.prepare_field_name();
self
}
fn content_type_name(mut self) -> Self {
self.prepare_content_type_name();
self
}
}
pub trait NameFallback {
fn apply(self, builder: &mut dyn NameBuilder);
}
impl NameFallback for &dyn NameBuilder {
fn apply(self, builder: &mut dyn NameBuilder) {
builder.merge(self);
}
}
impl NameFallback for Box<dyn NameBuilder> {
fn apply(self, builder: &mut dyn NameBuilder) {
builder.merge(&*self);
}
}
impl NameFallback for Name {
#[inline]
fn apply(self, builder: &mut dyn NameBuilder) {
(&self).apply(builder);
}
}
impl NameFallback for &Name {
#[inline]
fn apply(self, builder: &mut dyn NameBuilder) {
builder.set_name(self.as_str().to_owned());
builder.set_generated(self.is_generated());
builder.set_with_id(false);
}
}
impl NameFallback for Option<&Name> {
#[inline]
fn apply(self, builder: &mut dyn NameBuilder) {
if let Some(x) = self {
x.apply(builder);
}
}
}
impl NameFallback for Option<Name> {
#[inline]
fn apply(self, builder: &mut dyn NameBuilder) {
self.as_ref().apply(builder);
}
}
impl NameFallback for &Option<Name> {
fn apply(self, builder: &mut dyn NameBuilder) {
self.as_ref().apply(builder);
}
}
impl NameFallback for &String {
fn apply(self, builder: &mut dyn NameBuilder) {
builder.set_name(self.to_owned());
builder.set_with_id(false);
}
}
impl NameFallback for Option<&String> {
fn apply(self, builder: &mut dyn NameBuilder) {
if let Some(x) = self {
x.apply(builder);
}
}
}
impl NameFallback for Option<String> {
fn apply(self, builder: &mut dyn NameBuilder) {
self.as_ref().apply(builder);
}
}
impl NameFallback for &Option<String> {
fn apply(self, builder: &mut dyn NameBuilder) {
self.as_ref().apply(builder);
}
}
impl NameFallback for &str {
fn apply(self, builder: &mut dyn NameBuilder) {
builder.set_name(self.to_owned());
builder.set_with_id(false);
}
}
impl NameFallback for Option<&str> {
fn apply(self, builder: &mut dyn NameBuilder) {
if let Some(x) = self {
x.apply(builder);
}
}
}