radicle_cob/
signatures.rs1use std::{
4 collections::BTreeMap,
5 convert::TryFrom,
6 iter::FromIterator,
7 ops::{Deref, DerefMut},
8};
9
10use crypto::{ssh, PublicKey};
11use git_ext::commit::{
12 headers::Signature::{Pgp, Ssh},
13 Commit,
14};
15
16pub use ssh::ExtendedSignature;
17pub mod error;
18
19#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
22pub struct Signatures(BTreeMap<PublicKey, crypto::Signature>);
23
24impl Deref for Signatures {
25 type Target = BTreeMap<PublicKey, crypto::Signature>;
26
27 fn deref(&self) -> &Self::Target {
28 &self.0
29 }
30}
31
32impl DerefMut for Signatures {
33 fn deref_mut(&mut self) -> &mut Self::Target {
34 &mut self.0
35 }
36}
37
38impl From<ExtendedSignature> for Signatures {
39 fn from(ExtendedSignature { key, sig }: ExtendedSignature) -> Self {
40 let mut map = BTreeMap::new();
41 map.insert(key, sig);
42 map.into()
43 }
44}
45
46impl From<BTreeMap<PublicKey, crypto::Signature>> for Signatures {
47 fn from(map: BTreeMap<PublicKey, crypto::Signature>) -> Self {
48 Self(map)
49 }
50}
51
52impl From<Signatures> for BTreeMap<PublicKey, crypto::Signature> {
53 fn from(s: Signatures) -> Self {
54 s.0
55 }
56}
57
58impl TryFrom<&Commit> for Signatures {
59 type Error = error::Signatures;
60
61 fn try_from(value: &Commit) -> Result<Self, Self::Error> {
62 value
63 .signatures()
64 .filter_map(|signature| {
65 match signature {
66 Pgp(_) => None,
68 Ssh(pem) => Some(
69 ExtendedSignature::from_pem(pem.as_bytes())
70 .map_err(error::Signatures::from),
71 ),
72 }
73 })
74 .map(|r| r.map(|es| (es.key, es.sig)))
75 .collect::<Result<_, _>>()
76 }
77}
78
79impl FromIterator<(PublicKey, crypto::Signature)> for Signatures {
80 fn from_iter<T>(iter: T) -> Self
81 where
82 T: IntoIterator<Item = (PublicKey, crypto::Signature)>,
83 {
84 Self(BTreeMap::from_iter(iter))
85 }
86}
87
88impl IntoIterator for Signatures {
89 type Item = (PublicKey, crypto::Signature);
90 type IntoIter = <BTreeMap<PublicKey, crypto::Signature> as IntoIterator>::IntoIter;
91
92 fn into_iter(self) -> Self::IntoIter {
93 self.0.into_iter()
94 }
95}
96
97impl Extend<ExtendedSignature> for Signatures {
98 fn extend<T>(&mut self, iter: T)
99 where
100 T: IntoIterator<Item = ExtendedSignature>,
101 {
102 for ExtendedSignature { key, sig } in iter {
103 self.insert(key, sig);
104 }
105 }
106}
107
108impl Extend<(PublicKey, crypto::Signature)> for Signatures {
109 fn extend<T>(&mut self, iter: T)
110 where
111 T: IntoIterator<Item = (PublicKey, crypto::Signature)>,
112 {
113 for (key, sig) in iter {
114 self.insert(key, sig);
115 }
116 }
117}