xsd_parser/types/
custom.rs

1//! Contains the [`CustomType`] type information and all related types.
2
3use std::fmt::{Debug, Formatter, Result as FmtResult};
4use std::hash::{Hash, Hasher};
5
6use proc_macro2::TokenStream;
7
8/// Type information for a custom defined type.
9pub struct CustomType {
10    name: &'static str,
11    default: Option<Box<dyn CustomDefaultImpl>>,
12}
13
14impl CustomType {
15    /// Create a new custom type information with the passed `name`.
16    #[must_use]
17    pub fn new(name: &'static str) -> Self {
18        Self {
19            name,
20            default: None,
21        }
22    }
23
24    /// Get the name of the custom defined type.
25    #[must_use]
26    pub fn name(&self) -> &'static str {
27        self.name
28    }
29
30    /// Try to get the default value (as code) for the given string.
31    ///
32    /// This is used to translate default values specified in the XSD schema,
33    /// to suitable rust code.
34    #[must_use]
35    pub fn default(&self, s: &str) -> Option<TokenStream> {
36        self.default.as_ref()?.exec(s)
37    }
38
39    /// Set the handler for the default values for this custom defined type.
40    #[must_use]
41    pub fn with_default<X: CustomDefaultImpl>(mut self, x: X) -> Self {
42        self.default = Some(Box::new(x));
43
44        self
45    }
46}
47
48impl Clone for CustomType {
49    fn clone(&self) -> Self {
50        Self {
51            name: self.name,
52            default: self
53                .default
54                .as_ref()
55                .map(|x| CustomDefaultImpl::clone(&**x)),
56        }
57    }
58}
59
60impl Debug for CustomType {
61    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
62        f.debug_struct("CustomType")
63            .field("name", &self.name)
64            .field("default", &self.default.is_some())
65            .finish()
66    }
67}
68
69impl Eq for CustomType {}
70
71impl PartialEq for CustomType {
72    fn eq(&self, other: &Self) -> bool {
73        self.name.eq(other.name)
74    }
75}
76
77impl Hash for CustomType {
78    fn hash<H: Hasher>(&self, state: &mut H) {
79        self.name.hash(state);
80    }
81}
82
83/// Trait that converts the default value of a element specified in the XML
84/// schema to actual default code.
85///
86/// You can add a custom default implementation to your custom type using
87/// [`CustomType::with_default`].
88pub trait CustomDefaultImpl: 'static {
89    /// Try to convert the passed string `s` that contains the default value from
90    /// the XML schema to actual default code. If the value could not be converted
91    /// to code `None` is returned.
92    fn exec(&self, s: &str) -> Option<TokenStream>;
93
94    /// Clone this instance and return it as a box.
95    fn clone(&self) -> Box<dyn CustomDefaultImpl>;
96}
97
98impl<X> CustomDefaultImpl for X
99where
100    X: Fn(&str) -> Option<TokenStream> + Clone + 'static,
101{
102    fn exec(&self, s: &str) -> Option<TokenStream> {
103        (*self)(s)
104    }
105
106    fn clone(&self) -> Box<dyn CustomDefaultImpl> {
107        Box::new(self.clone())
108    }
109}