tor_netdoc/parse2/
impls.rs

1//! Implementations of our useful traits, on external and parsing-mode types
2
3use super::*;
4
5/// Types related to RSA keys
6mod rsa {
7    use super::*;
8    use tor_llcrypto::pk::rsa::PublicKey;
9
10    /// An item which contains an RSA public key as an Object, and no extra arguments
11    #[derive(Deftly)]
12    #[derive_deftly(ItemValueParseable)]
13    #[deftly(netdoc(no_extra_args))]
14    struct ParsePublicKey {
15        /// The public key data
16        #[deftly(netdoc(object))]
17        key: PublicKey,
18    }
19
20    impl ItemObjectParseable for PublicKey {
21        fn check_label(label: &str) -> Result<(), EP> {
22            match label {
23                "RSA PUBLIC KEY" => Ok(()),
24                _ => Err(EP::ObjectIncorrectLabel),
25            }
26        }
27        fn from_bytes(input: &[u8]) -> Result<Self, EP> {
28            PublicKey::from_der(input).ok_or(EP::ObjectInvalidData)
29        }
30    }
31
32    impl ItemValueParseable for PublicKey {
33        fn from_unparsed(item: UnparsedItem) -> Result<Self, EP> {
34            Ok(ParsePublicKey::from_unparsed(item)?.key)
35        }
36    }
37}
38
39/// Types related to times
40pub(crate) mod times {
41    use super::*;
42    use crate::types::misc::Iso8601TimeSp;
43
44    /// Date and time in deprecated ISO8601-with-space separate arguments syntax
45    ///
46    /// Eg `dir-key-published` in a dir auth key cert.
47    // TODO this should be
48    //   #[deprecated = "use the Iso8601TimeSp name instead"]
49    // but right now we have too much outstanding work in flight to do that.
50    pub type NdaSystemTimeDeprecatedSyntax = Iso8601TimeSp;
51
52    impl ItemArgumentParseable for NdaSystemTimeDeprecatedSyntax {
53        fn from_args<'s>(args: &mut ArgumentStream<'s>) -> Result<Self, ArgumentError> {
54            let t;
55            (t, *args) = (|| {
56                let whole_line_len = args.whole_line_len();
57                let options = args.parse_options();
58                let args = args.clone().into_remaining();
59                let spc2 = args
60                    .match_indices(WS)
61                    .nth(1)
62                    .map(|(spc2, _)| spc2)
63                    .unwrap_or_else(|| args.len());
64                let (t, rest) = args.split_at(spc2);
65                let t: crate::types::misc::Iso8601TimeSp =
66                    t.parse().map_err(|_| ArgumentError::Invalid)?;
67                Ok::<_, AE>((t, ArgumentStream::new(rest, whole_line_len, options)))
68            })()?;
69            Ok(t)
70        }
71    }
72}
73
74/// Protocol versions (from `tor-protover`)
75pub(crate) mod protovers {
76    use super::*;
77    use tor_protover::Protocols;
78
79    impl ItemValueParseable for Protocols {
80        fn from_unparsed(item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
81            item.check_no_object()?;
82            item.args_copy()
83                .into_remaining()
84                .parse()
85                .map_err(item.invalid_argument_handler("protocols"))
86        }
87    }
88}
89
90/// Implementations on `Void`
91pub(crate) mod void_impls {
92    use super::*;
93
94    impl ItemValueParseable for Void {
95        fn from_unparsed(_item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
96            Err(EP::ItemForbidden)
97        }
98    }
99
100    #[cfg(feature = "parse2")]
101    impl ItemObjectParseable for Void {
102        fn check_label(_label: &str) -> Result<(), ErrorProblem> {
103            Ok(())
104        }
105
106        fn from_bytes(_input: &[u8]) -> Result<Self, ErrorProblem> {
107            Err(EP::ObjectUnexpected)
108        }
109    }
110}
111
112/// Conversion module for `Vec<u8>` as Object with [`ItemValueParseable`]
113pub mod raw_data_object {
114    use super::*;
115
116    /// "Parse" the data
117    pub fn try_from(data: Vec<u8>) -> Result<Vec<u8>, Void> {
118        Ok(data)
119    }
120}