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

            
3
use super::*;
4

            
5
impl ItemArgument for str {
6
98212
    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
2971200
        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
98212
        }
15
98212
        out.args_raw_nonempty(&self);
16
98212
        Ok(())
17
98212
    }
18
}
19

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

            
26
impl ItemArgument for Iso8601TimeSp {
27
    // Unlike the macro'd formats, contains a space while still being one argument
28
22
    fn write_arg_onto(&self, out: &mut ItemEncoder<'_>) -> Result<(), Bug> {
29
22
        let arg = self.to_string();
30
22
        out.args_raw_nonempty(&arg.as_str());
31
22
        Ok(())
32
22
    }
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
4
    fn encode_fields(&self, out: &mut NetdocEncoder) -> Result<(), Bug> {
58
4
        <T as NetdocEncodableFields>::encode_fields(self, out)
59
4
    }
60
}
61

            
62
impl<T: ItemValueEncodable> ItemValueEncodable for Arc<T> {
63
14
    fn write_item_value_onto(&self, out: ItemEncoder) -> Result<(), Bug> {
64
14
        <T as ItemValueEncodable>::write_item_value_onto(self, out)
65
14
    }
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
44
        fn write_item_value_onto(&self, mut out: ItemEncoder) -> Result<(), Bug> {
113
44
            out.args_raw_string(&self);
114
44
            Ok(())
115
44
        }
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
}