xmpp_parsers/
starttls.rs

1// Copyright (c) 2024 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use xso::{AsXml, FromXml};
8
9use crate::ns;
10
11/// Request to start TLS.
12#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
13#[xml(namespace = ns::TLS, name = "starttls")]
14pub struct Request;
15
16/// Information that TLS may now commence.
17#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
18#[xml(namespace = ns::TLS, name = "proceed")]
19pub struct Proceed;
20
21/// Stream feature for StartTLS
22///
23/// Used in [`crate::stream_features::StreamFeatures`].
24#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
25#[xml(namespace = ns::TLS, name = "starttls")]
26pub struct StartTls {
27    /// Marker for mandatory StartTLS.
28    #[xml(flag)]
29    pub required: bool,
30}
31
32/// Enum which allows parsing/serialising any STARTTLS element.
33#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
34#[xml()]
35pub enum Nonza {
36    /// Request to start TLS
37    #[xml(transparent)]
38    Request(Request),
39
40    /// Information that TLS may now commence
41    #[xml(transparent)]
42    Proceed(Proceed),
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use minidom::Element;
49
50    #[test]
51    fn test_size() {
52        assert_size!(Request, 0);
53        assert_size!(Proceed, 0);
54        assert_size!(StartTls, 1);
55        assert_size!(Nonza, 1);
56    }
57
58    #[test]
59    fn test_parsers() {
60        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
61            .parse()
62            .unwrap();
63        let request = Request::try_from(elem.clone()).unwrap();
64        let elem2 = Element::from(request);
65        assert_eq!(elem, elem2);
66
67        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
68            .parse()
69            .unwrap();
70        let proceed = Proceed::try_from(elem.clone()).unwrap();
71        let elem2 = Element::from(proceed);
72        assert_eq!(elem, elem2);
73
74        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
75            .parse()
76            .unwrap();
77        let starttls = StartTls::try_from(elem.clone()).unwrap();
78        assert_eq!(starttls.required, false);
79        let elem2 = Element::from(starttls);
80        assert_eq!(elem, elem2);
81
82        let elem: Element =
83            "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls>"
84                .parse()
85                .unwrap();
86        let starttls = StartTls::try_from(elem.clone()).unwrap();
87        assert_eq!(starttls.required, true);
88        let elem2 = Element::from(starttls);
89        assert_eq!(elem, elem2);
90
91        let elem: Element = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
92            .parse()
93            .unwrap();
94        let nonza = Nonza::try_from(elem.clone()).unwrap();
95        assert_eq!(nonza, Nonza::Request(Request));
96        let elem2 = Element::from(nonza);
97        assert_eq!(elem, elem2);
98
99        let elem: Element = "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
100            .parse()
101            .unwrap();
102        let nonza = Nonza::try_from(elem.clone()).unwrap();
103        assert_eq!(nonza, Nonza::Proceed(Proceed));
104        let elem2 = Element::from(nonza);
105        assert_eq!(elem, elem2);
106    }
107}