Skip to main content

xsd_parser/models/meta/
custom.rs

1//! Contains the [`CustomMeta`] type information and all related types.
2
3use std::fmt::{Debug, Formatter, Result as FmtResult};
4use std::hash::{Hash, Hasher};
5
6use xsd_parser_types::misc::Namespace;
7
8use crate::config::NamespaceId;
9use crate::pipeline::generator::{ValueGenerator, ValueGeneratorBox};
10
11/// Type information for a custom defined type.
12pub struct CustomMeta {
13    /// Name of the custom defined type.
14    pub name: String,
15
16    /// The path the type should be included from.
17    ///
18    /// The path should be absolute, or relative to the root of the generated code.
19    pub include: Option<String>,
20
21    /// The handler for the default values for this custom defined type.
22    ///
23    /// This is used to translate default values specified in the XSD schema,
24    /// to suitable rust code.
25    pub default: Option<ValueGeneratorBox>,
26
27    /// The namespaces needed by this custom type.
28    pub namespaces: Vec<CustomMetaNamespace>,
29
30    /// Wether this custom type contains `xs:any` elements or not.
31    pub allow_any: bool,
32}
33
34impl CustomMeta {
35    /// Create a new custom type information with the passed `name`.
36    #[must_use]
37    pub fn new<X>(name: X) -> Self
38    where
39        X: Into<String>,
40    {
41        Self {
42            name: name.into(),
43            include: None,
44            default: None,
45            namespaces: Vec::new(),
46            allow_any: false,
47        }
48    }
49
50    /// Get the name of the custom defined type.
51    #[must_use]
52    pub fn name(&self) -> &str {
53        &self.name
54    }
55
56    /// Get the include path of the custom defined type.
57    #[must_use]
58    pub fn include(&self) -> Option<&str> {
59        self.include.as_deref()
60    }
61
62    /// The the path the type should be included from.
63    ///
64    /// The path should be absolute, or relative to the root of the generated code.
65    #[must_use]
66    pub fn include_from<X>(mut self, include: X) -> Self
67    where
68        X: Into<String>,
69    {
70        self.include = Some(include.into());
71
72        self
73    }
74
75    /// Set the handler for the default values for this custom defined type.
76    #[must_use]
77    pub fn with_default<X: ValueGenerator>(mut self, x: X) -> Self {
78        self.default = Some(Box::new(x));
79
80        self
81    }
82
83    /// Add a namespace that is needed by this custom type.
84    ///
85    /// The namespace may be added to the root element during serialization.
86    #[must_use]
87    pub fn with_namespace<N>(mut self, ns: N) -> Self
88    where
89        N: Into<CustomMetaNamespace>,
90    {
91        self.namespaces.push(ns.into());
92
93        self
94    }
95
96    /// Returns the namespaces needed by this custom type.
97    #[must_use]
98    pub fn namespaces(&self) -> &[CustomMetaNamespace] {
99        &self.namespaces
100    }
101
102    /// Returns `true` if this type contains `xs:any` elements, `false` otherwise.
103    #[must_use]
104    pub fn allow_any(&self) -> bool {
105        self.allow_any
106    }
107
108    /// Set wether this custom type contains`xs:any` elements or not.
109    #[must_use]
110    pub fn with_allow_any(mut self, value: bool) -> Self {
111        self.allow_any = value;
112
113        self
114    }
115}
116
117impl Clone for CustomMeta {
118    fn clone(&self) -> Self {
119        Self {
120            name: self.name.clone(),
121            include: self.include.clone(),
122            default: self.default.as_ref().map(|x| ValueGenerator::clone(&**x)),
123            namespaces: self.namespaces.clone(),
124            allow_any: self.allow_any,
125        }
126    }
127}
128
129impl Debug for CustomMeta {
130    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
131        f.debug_struct("CustomType")
132            .field("name", &self.name)
133            .field("include", &self.include)
134            .field("default", &self.default.is_some())
135            .field("namespaces", &self.namespaces)
136            .field("allow_any", &self.allow_any)
137            .finish()
138    }
139}
140
141impl Eq for CustomMeta {}
142
143impl PartialEq for CustomMeta {
144    fn eq(&self, other: &Self) -> bool {
145        self.name.eq(&other.name)
146    }
147}
148
149impl Hash for CustomMeta {
150    fn hash<H: Hasher>(&self, state: &mut H) {
151        self.name.hash(state);
152    }
153}
154
155/// Namespace information for a custom defined type.
156#[derive(Debug, Clone, Eq, PartialEq, Hash)]
157pub enum CustomMetaNamespace {
158    /// A namespace that is identified by its id.
159    Id(NamespaceId),
160
161    /// A namespace that is identified by the namespace information itself.
162    Namespace(Namespace),
163}
164
165impl From<NamespaceId> for CustomMetaNamespace {
166    fn from(value: NamespaceId) -> Self {
167        Self::Id(value)
168    }
169}
170
171impl From<Namespace> for CustomMetaNamespace {
172    fn from(value: Namespace) -> Self {
173        Self::Namespace(value)
174    }
175}