ssh_agent/proto/
key_type.rs1pub trait KeyTypeEnum {
2 fn key_type(&self) -> String;
3}
4
5pub trait KeyType {
6 const KEY_TYPE: &'static str;
7 fn key_type(&self) -> String {
8 Self::KEY_TYPE.to_string()
9 }
10}
11
12macro_rules! impl_key_type_enum_ser_de {
13 ($class_name:path, $(($variant_name:path, $variant_class:ty)),* ) => {
14 impl KeyTypeEnum for $class_name {
15 fn key_type(&self) -> String {
16 match self {
17 $($variant_name(key) => key.key_type()),*
18 }
19 }
20 }
21
22 impl Serialize for $class_name {
23 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
24 let mut serialize_tuple = serializer.serialize_tuple(2)?;
25
26 match self {
27 $(
28 $variant_name(key) => {
29 serialize_tuple.serialize_element(&key.key_type())?;
30 serialize_tuple.serialize_element(key)?;
31 }
32 ),*
33 };
34 serialize_tuple.end()
35 }
36 }
37
38 impl<'de> Deserialize<'de> for $class_name {
39 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<$class_name, D::Error> {
40 struct KeyVisitor;
41
42 impl<'de> serde::de::Visitor<'de> for KeyVisitor {
43 type Value = $class_name;
44
45 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
46 formatter.write_str("Key with format (type, key)")
47 }
48
49 fn visit_seq<V: serde::de::SeqAccess<'de>>(
50 self,
51 mut seq: V
52 ) -> Result<Self::Value, V::Error> {
53 let key_type: String = seq.next_element()?
54 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
55 let key_type_str = key_type.as_str();
56
57 $(
58 if key_type_str.starts_with(<$variant_class>::KEY_TYPE) {
59 let key: $variant_class = seq.next_element()?
60 .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
61 return Ok($variant_name(key))
62 }
63 )*
64
65 return Err(Error::custom(ProtoError::UnexpectedVariant));
66 }
67 }
68
69 deserializer.deserialize_tuple(2, KeyVisitor)
70 }
71 }
72 };
73}