salvo_oapi/openapi/
xml.rs

1//! Implements [OpenAPI Xml Object][xml_object] types.
2//!
3//! [xml_object]: https://spec.openapis.org/oas/latest.html#xml-object
4use std::borrow::Cow;
5
6use serde::{Deserialize, Serialize};
7
8/// Implements [OpenAPI Xml Object][xml_object].
9///
10/// Can be used to modify xml output format of specific [OpenAPI Schema Object][schema_object] which are
11/// implemented in [`schema`][schema] module.
12///
13/// [xml_object]: https://spec.openapis.org/oas/latest.html#xml-object
14/// [schema_object]: https://spec.openapis.org/oas/latest.html#schema-object
15/// [schema]: ../schema/index.html
16#[non_exhaustive]
17#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
18pub struct Xml {
19    /// Used to replace the name of attribute or type used in schema property.
20    /// When used with [`Xml::wrapped`] attribute the name will be used as a wrapper name
21    /// for wrapped array instead of the item or type name.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub name: Option<Cow<'static, str>>,
24
25    /// Valid uri definition of namespace used in xml.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub namespace: Option<Cow<'static, str>>,
28
29    /// Prefix for xml element [`Xml::name`].
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub prefix: Option<Cow<'static, str>>,
32
33    /// Flag deciding will this attribute translate to element attribute instead of xml element.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub attribute: Option<bool>,
36
37    /// Flag only usable with array definition. If set to true the output xml will wrap the array of items
38    /// `<pets><pet></pet></pets>` instead of unwrapped `<pet></pet>`.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub wrapped: Option<bool>,
41}
42
43impl Xml {
44    /// Construct a new [`Xml`] object.
45    #[must_use]
46    pub fn new() -> Self {
47        Self {
48            ..Default::default()
49        }
50    }
51}
52
53impl Xml {
54    /// Add [`Xml::name`] to xml object.
55    ///
56    /// Builder style chainable consuming add name method.
57    #[must_use]
58    pub fn name<S: Into<Cow<'static, str>>>(mut self, name: S) -> Self {
59        self.name = Some(name.into());
60        self
61    }
62
63    /// Add [`Xml::namespace`] to xml object.
64    ///
65    /// Builder style chainable consuming add namespace method.
66    #[must_use]
67    pub fn namespace<S: Into<Cow<'static, str>>>(mut self, namespace: S) -> Self {
68        self.namespace = Some(namespace.into());
69        self
70    }
71
72    /// Add [`Xml::prefix`] to xml object.
73    ///
74    /// Builder style chainable consuming add prefix method.
75    #[must_use]
76    pub fn prefix<S: Into<Cow<'static, str>>>(mut self, prefix: S) -> Self {
77        self.prefix = Some(prefix.into());
78        self
79    }
80
81    /// Mark [`Xml`] object as attribute. See [`Xml::attribute`]
82    ///
83    /// Builder style chainable consuming add attribute method.
84    #[must_use]
85    pub fn attribute(mut self, attribute: bool) -> Self {
86        self.attribute = Some(attribute);
87        self
88    }
89
90    /// Mark [`Xml`] object wrapped. See [`Xml::wrapped`]
91    ///
92    /// Builder style chainable consuming add wrapped method.
93    #[must_use]
94    pub fn wrapped(mut self, wrapped: bool) -> Self {
95        self.wrapped = Some(wrapped);
96        self
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::Xml;
103
104    #[test]
105    fn xml_new() {
106        let mut xml = Xml::new();
107
108        assert!(xml.name.is_none());
109        assert!(xml.namespace.is_none());
110        assert!(xml.prefix.is_none());
111        assert!(xml.attribute.is_none());
112        assert!(xml.wrapped.is_none());
113
114        xml = xml.name("name");
115        assert!(xml.name.is_some());
116
117        xml = xml.namespace("namespave");
118        assert!(xml.namespace.is_some());
119
120        xml = xml.prefix("prefix");
121        assert!(xml.prefix.is_some());
122
123        xml = xml.attribute(true);
124        assert!(xml.attribute.is_some());
125
126        xml = xml.wrapped(true);
127        assert!(xml.wrapped.is_some());
128    }
129}