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 args = args.clone().into_remaining();
58                let spc2 = args
59                    .match_indices(WS)
60                    .nth(1)
61                    .map(|(spc2, _)| spc2)
62                    .unwrap_or_else(|| args.len());
63                let (t, rest) = args.split_at(spc2);
64                let t: crate::types::misc::Iso8601TimeSp =
65                    t.parse().map_err(|_| ArgumentError::Invalid)?;
66                Ok::<_, AE>((t, ArgumentStream::new(rest, whole_line_len)))
67            })()?;
68            Ok(t)
69        }
70    }
71}
72
73/// Protocol versions (from `tor-protover`)
74pub(crate) mod protovers {
75    use super::*;
76    use tor_protover::Protocols;
77
78    impl ItemValueParseable for Protocols {
79        fn from_unparsed(item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
80            item.check_no_object()?;
81            item.args_copy()
82                .into_remaining()
83                .parse()
84                .map_err(item.invalid_argument_handler("protocols"))
85        }
86    }
87}
88
89/// Implementations on `Void`
90pub(crate) mod void_impls {
91    use super::*;
92
93    impl ItemValueParseable for Void {
94        fn from_unparsed(_item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
95            Err(EP::ItemForbidden)
96        }
97    }
98
99    #[cfg(feature = "parse2")]
100    impl ItemObjectParseable for Void {
101        fn check_label(_label: &str) -> Result<(), ErrorProblem> {
102            Ok(())
103        }
104
105        fn from_bytes(_input: &[u8]) -> Result<Self, ErrorProblem> {
106            Err(EP::ObjectUnexpected)
107        }
108    }
109}
110
111/// Conversion module for `Vec<u8>` as Object with [`ItemValueParseable`]
112pub mod raw_data_object {
113    use super::*;
114
115    /// "Parse" the data
116    pub fn try_from(data: Vec<u8>) -> Result<Vec<u8>, Void> {
117        Ok(data)
118    }
119}