use std::any::{Any, TypeId};
use std::fmt::Debug;
use bitflags::bitflags;
use xsd_parser_types::misc::Namespace;
use crate::models::code::IdentPath;
use crate::pipeline::renderer::{
NamespaceSerialization, RenderStep as RenderStepTrait, RenderStepType,
};
#[derive(Debug)]
pub struct RendererConfig {
pub steps: Vec<Box<dyn RenderStepConfig>>,
pub flags: RendererFlags,
pub derive: Option<Vec<String>>,
pub alloc: String,
pub dyn_type_traits: Option<Vec<String>>,
pub xsd_parser_types: String,
}
impl Default for RendererConfig {
fn default() -> Self {
Self {
steps: vec![Box::new(RenderStep::Types)],
flags: RendererFlags::empty(),
derive: None,
alloc: "std".into(),
dyn_type_traits: None,
xsd_parser_types: "xsd_parser_types".into(),
}
}
}
impl Clone for RendererConfig {
fn clone(&self) -> Self {
Self {
steps: self.steps.iter().map(|x| x.boxed_clone()).collect(),
flags: self.flags,
derive: self.derive.clone(),
alloc: self.alloc.clone(),
dyn_type_traits: self.dyn_type_traits.clone(),
xsd_parser_types: self.xsd_parser_types.clone(),
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct RendererFlags: u32 {
#[doc = include_str!("../../tests/renderer/renderer_flags/schema.xsd")]
#[doc = include_str!("../../tests/renderer/renderer_flags/expected/empty.rs")]
const NONE = 0;
#[doc = include_str!("../../tests/renderer/renderer_flags/schema_with_docs.xsd")]
#[doc = include_str!("../../tests/renderer/renderer_flags/expected/render_docs.rs")]
const RENDER_DOCS = Self::RENDER_TYPE_DOCS.bits()
| Self::RENDER_ELEMENT_DOCS.bits()
| Self::RENDER_ATTRIBUTE_DOCS.bits()
| Self::RENDER_VARIANT_DOCS.bits();
const RENDER_TYPE_DOCS = 1 << 0;
const RENDER_ELEMENT_DOCS = 1 << 1;
const RENDER_ATTRIBUTE_DOCS = 1 << 2;
const RENDER_VARIANT_DOCS = 1 << 3;
}
}
#[derive(Debug, Clone)]
pub enum RenderStep {
Types,
TypesSerdeXmlRs {
version: SerdeXmlRsVersion,
},
TypesSerdeQuickXml,
Defaults,
NamespaceConstants,
EnumConstants,
PrefixConstants,
WithNamespaceTrait,
QuickXmlSerialize {
namespaces: NamespaceSerialization,
default_namespace: Option<Namespace>,
},
QuickXmlDeserialize {
boxed_deserializer: bool,
},
QuickXmlCollectNamespaces,
}
pub trait RenderStepConfig: Debug + Any {
fn boxed_clone(&self) -> Box<dyn RenderStepConfig>;
fn into_render_step(self: Box<Self>) -> Box<dyn RenderStepTrait>;
fn render_step_type(&self) -> RenderStepType {
RenderStepType::Undefined
}
fn is_mutual_exclusive_to(&self, other: &dyn RenderStepConfig) -> bool {
self.type_id() == other.type_id()
|| self
.render_step_type()
.is_mutual_exclusive_to(other.render_step_type())
}
}
impl<X> RenderStepConfig for X
where
X: RenderStepTrait + Clone + Any + 'static,
{
fn render_step_type(&self) -> RenderStepType {
X::render_step_type(self)
}
fn boxed_clone(&self) -> Box<dyn RenderStepConfig> {
Box::new(self.clone())
}
fn into_render_step(self: Box<Self>) -> Box<dyn RenderStepTrait> {
self
}
}
impl RenderStepConfig for RenderStep {
fn render_step_type(&self) -> RenderStepType {
match self {
Self::Types => RenderStepType::Types,
Self::TypesSerdeXmlRs { .. } => RenderStepType::Types,
Self::TypesSerdeQuickXml => RenderStepType::Types,
Self::Defaults => RenderStepType::ExtraImpls,
Self::EnumConstants => RenderStepType::ExtraImpls,
Self::PrefixConstants => RenderStepType::ExtraImpls,
Self::NamespaceConstants => RenderStepType::ExtraImpls,
Self::WithNamespaceTrait => RenderStepType::ExtraImpls,
Self::QuickXmlSerialize { .. } => RenderStepType::ExtraImpls,
Self::QuickXmlDeserialize { .. } => RenderStepType::ExtraImpls,
Self::QuickXmlCollectNamespaces => RenderStepType::ExtraImpls,
}
}
fn boxed_clone(&self) -> Box<dyn RenderStepConfig> {
Box::new(self.clone())
}
fn into_render_step(self: Box<Self>) -> Box<dyn RenderStepTrait> {
use crate::pipeline::renderer::{
DefaultsRenderStep, EnumConstantsRenderStep, NamespaceConstantsRenderStep,
PrefixConstantsRenderStep, QuickXmlCollectNamespacesRenderStep,
QuickXmlDeserializeRenderStep, QuickXmlSerializeRenderStep,
SerdeQuickXmlTypesRenderStep, SerdeXmlRsV7TypesRenderStep, SerdeXmlRsV8TypesRenderStep,
TypesRenderStep, WithNamespaceTraitRenderStep,
};
match *self {
Self::Types => Box::new(TypesRenderStep),
Self::TypesSerdeXmlRs {
version: SerdeXmlRsVersion::Version07AndBelow,
} => Box::new(SerdeXmlRsV7TypesRenderStep),
Self::TypesSerdeXmlRs {
version: SerdeXmlRsVersion::Version08AndAbove,
} => Box::new(SerdeXmlRsV8TypesRenderStep),
Self::TypesSerdeQuickXml => Box::new(SerdeQuickXmlTypesRenderStep),
Self::Defaults => Box::new(DefaultsRenderStep),
Self::EnumConstants => Box::new(EnumConstantsRenderStep),
Self::PrefixConstants => Box::new(PrefixConstantsRenderStep::default()),
Self::NamespaceConstants => Box::new(NamespaceConstantsRenderStep::default()),
Self::WithNamespaceTrait => Box::new(WithNamespaceTraitRenderStep),
Self::QuickXmlSerialize {
namespaces,
default_namespace,
} => Box::new(QuickXmlSerializeRenderStep {
namespaces,
default_namespace,
}),
Self::QuickXmlDeserialize { boxed_deserializer } => {
Box::new(QuickXmlDeserializeRenderStep { boxed_deserializer })
}
Self::QuickXmlCollectNamespaces => Box::new(QuickXmlCollectNamespacesRenderStep),
}
}
fn is_mutual_exclusive_to(&self, other: &dyn RenderStepConfig) -> bool {
use crate::pipeline::renderer::{
DefaultsRenderStep, NamespaceConstantsRenderStep, QuickXmlCollectNamespacesRenderStep,
QuickXmlDeserializeRenderStep, QuickXmlSerializeRenderStep,
SerdeQuickXmlTypesRenderStep, SerdeXmlRsV7TypesRenderStep, SerdeXmlRsV8TypesRenderStep,
TypesRenderStep, WithNamespaceTraitRenderStep,
};
if self
.render_step_type()
.is_mutual_exclusive_to(other.render_step_type())
{
return true;
}
let other_id = other.type_id();
let other = (other as &dyn Any).downcast_ref::<Self>();
match (self, other) {
(Self::Types, Some(Self::Types)) => true,
(Self::TypesSerdeXmlRs { .. }, Some(Self::TypesSerdeXmlRs { .. })) => true,
(Self::TypesSerdeQuickXml, Some(Self::TypesSerdeQuickXml)) => true,
(Self::Defaults, Some(Self::Defaults)) => true,
(Self::NamespaceConstants, Some(Self::NamespaceConstants)) => true,
(Self::WithNamespaceTrait, Some(Self::WithNamespaceTrait)) => true,
(Self::QuickXmlSerialize { .. }, Some(Self::QuickXmlSerialize { .. })) => true,
(Self::QuickXmlDeserialize { .. }, Some(Self::QuickXmlDeserialize { .. })) => true,
(Self::QuickXmlCollectNamespaces, Some(Self::QuickXmlCollectNamespaces)) => true,
(Self::Types, None) => other_id == TypeId::of::<TypesRenderStep>(),
(
Self::TypesSerdeXmlRs {
version: SerdeXmlRsVersion::Version07AndBelow,
},
None,
) => other_id == TypeId::of::<SerdeXmlRsV7TypesRenderStep>(),
(
Self::TypesSerdeXmlRs {
version: SerdeXmlRsVersion::Version08AndAbove,
},
None,
) => other_id == TypeId::of::<SerdeXmlRsV8TypesRenderStep>(),
(Self::TypesSerdeQuickXml, None) => {
other_id == TypeId::of::<SerdeQuickXmlTypesRenderStep>()
}
(Self::Defaults, None) => other_id == TypeId::of::<DefaultsRenderStep>(),
(Self::NamespaceConstants, None) => {
other_id == TypeId::of::<NamespaceConstantsRenderStep>()
}
(Self::WithNamespaceTrait, None) => {
other_id == TypeId::of::<WithNamespaceTraitRenderStep>()
}
(Self::QuickXmlSerialize { .. }, None) => {
other_id == TypeId::of::<QuickXmlSerializeRenderStep>()
}
(Self::QuickXmlDeserialize { .. }, None) => {
other_id == TypeId::of::<QuickXmlDeserializeRenderStep>()
}
(Self::QuickXmlCollectNamespaces, None) => {
other_id == TypeId::of::<QuickXmlCollectNamespacesRenderStep>()
}
_ => false,
}
}
}
impl RenderStep {
#[must_use]
pub fn is_same(&self, other: &Self) -> bool {
match (self, other) {
(
Self::Types | Self::TypesSerdeXmlRs { .. } | Self::TypesSerdeQuickXml,
Self::Types | Self::TypesSerdeXmlRs { .. } | Self::TypesSerdeQuickXml,
)
| (Self::Defaults, Self::Defaults)
| (Self::NamespaceConstants, Self::NamespaceConstants)
| (Self::WithNamespaceTrait, Self::WithNamespaceTrait)
| (Self::QuickXmlSerialize { .. }, Self::QuickXmlSerialize { .. })
| (Self::QuickXmlDeserialize { .. }, Self::QuickXmlDeserialize { .. })
| (Self::QuickXmlCollectNamespaces, Self::QuickXmlCollectNamespaces) => true,
(_, _) => false,
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SerdeXmlRsVersion {
Version07AndBelow,
Version08AndAbove,
}
#[derive(Default, Debug)]
pub enum DynTypeTraits {
#[default]
Auto,
Custom(Vec<IdentPath>),
}