1
//! Implementations of our useful traits, on external and parsing-mode types
2

            
3
use super::*;
4

            
5
impl ItemArgument for str {
6
95784
    fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
7
        // Implements this
8
        // https://gitlab.torproject.org/tpo/core/torspec/-/merge_requests/106
9
2909196
        if self.is_empty() || self.chars().any(|c| !c.is_ascii_graphic()) {
10
            return Err(internal!(
11
                "invalid netdoc keyword line argument syntax {:?}",
12
                self
13
            ));
14
95784
        }
15
95784
        out.args_raw_nonempty(&self);
16
95784
        Ok(())
17
95784
    }
18
}
19

            
20
impl ItemArgument for &str {
21
30622
    fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
22
30622
        <str as ItemArgument>::write_arg_onto(self, out)
23
30622
    }
24
}
25

            
26
impl ItemArgument for Iso8601TimeSp {
27
    // Unlike the macro'd formats, contains a space while still being one argument
28
10
    fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
29
10
        let arg = self.to_string();
30
10
        out.args_raw_nonempty(&arg.as_str());
31
10
        Ok(())
32
10
    }
33
}
34

            
35
impl ItemValueEncodable for Void {
36
    fn write_item_value_onto(&self, _out: ItemEncoder) -> Result<(), Bug> {
37
        void::unreachable(*self)
38
    }
39
}
40

            
41
impl ItemObjectEncodable for Void {
42
    fn label(&self) -> &str {
43
        void::unreachable(*self)
44
    }
45
    fn write_object_onto(&self, _: &mut Vec<u8>) -> Result<(), Bug> {
46
        void::unreachable(*self)
47
    }
48
}
49

            
50
impl<T: NetdocEncodable> NetdocEncodable for Arc<T> {
51
    fn encode_unsigned(&self, out: &mut NetdocEncoder) -> Result<(), Bug> {
52
        <T as NetdocEncodable>::encode_unsigned(self, out)
53
    }
54
}
55

            
56
impl<T: NetdocEncodableFields> NetdocEncodableFields for Arc<T> {
57
    fn encode_fields(&self, out: &mut NetdocEncoder) -> Result<(), Bug> {
58
        <T as NetdocEncodableFields>::encode_fields(self, out)
59
    }
60
}
61

            
62
impl<T: ItemValueEncodable> ItemValueEncodable for Arc<T> {
63
    fn write_item_value_onto(&self, out: ItemEncoder) -> Result<(), Bug> {
64
        <T as ItemValueEncodable>::write_item_value_onto(self, out)
65
    }
66
}
67

            
68
impl<T: ItemArgument> ItemArgument for Arc<T> {
69
    fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
70
        <T as ItemArgument>::write_arg_onto(self, out)
71
    }
72
}
73

            
74
impl<T: ItemObjectEncodable> ItemObjectEncodable for Arc<T> {
75
    fn label(&self) -> &str {
76
        <T as ItemObjectEncodable>::label(self)
77
    }
78
    fn write_object_onto(&self, b: &mut Vec<u8>) -> Result<(), Bug> {
79
        <T as ItemObjectEncodable>::write_object_onto(self, b)
80
    }
81
}
82

            
83
/// Types related to RSA keys
84
mod rsa {
85
    use super::*;
86
    use tor_llcrypto::pk::rsa::PublicKey;
87

            
88
    impl ItemObjectEncodable for PublicKey {
89
4
        fn label(&self) -> &str {
90
4
            "RSA PUBLIC KEY"
91
4
        }
92
4
        fn write_object_onto(&self, b: &mut Vec<u8>) -> Result<(), Bug> {
93
4
            b.extend(self.to_der());
94
4
            Ok(())
95
4
        }
96
    }
97

            
98
    impl ItemValueEncodable for PublicKey {
99
4
        fn write_item_value_onto(&self, out: ItemEncoder) -> Result<(), Bug> {
100
4
            out.object(self);
101
4
            Ok(())
102
4
        }
103
    }
104
}
105

            
106
/// Protocol versions (from `tor-protover`)
107
pub(crate) mod protovers {
108
    use super::*;
109
    use tor_protover::Protocols;
110

            
111
    impl ItemValueEncodable for Protocols {
112
        fn write_item_value_onto(&self, mut out: ItemEncoder) -> Result<(), Bug> {
113
            out.args_raw_string(&self);
114
            Ok(())
115
        }
116
    }
117
}
118

            
119
/// HS POW
120
#[cfg(feature = "hs-pow-full")]
121
mod hs_pow {
122
    use super::*;
123
    use tor_hscrypto::pow::v1;
124

            
125
    impl ItemArgument for v1::Seed {
126
2
        fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
127
2
            let mut seed_bytes = vec![];
128
2
            tor_bytes::Writer::write(&mut seed_bytes, &self)?;
129
2
            out.add_arg(&Base64Unpadded::encode_string(&seed_bytes));
130
2
            Ok(())
131
2
        }
132
    }
133

            
134
    impl ItemArgument for v1::Effort {
135
2
        fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
136
2
            out.add_arg(&<Self as Into<u32>>::into(*self));
137
2
            Ok(())
138
2
        }
139
    }
140
}