sequoia_openpgp/packet/
any.rs1use crate::packet::{
4 Packet,
5 Unknown,
6 Signature,
7 OnePassSig,
8 Key,
9 key,
10 Marker,
11 Trust,
12 UserID,
13 UserAttribute,
14 Literal,
15 CompressedData,
16 PKESK,
17 SKESK,
18 SEIP,
19 MDC,
20 Padding,
21};
22
23pub trait Any<T>: crate::seal::Sealed {
35 #[expect(clippy::result_large_err, reason = "returning the value on error is intentional")]
46 fn downcast(self) -> std::result::Result<T, Packet>;
47
48 fn downcast_ref(&self) -> Option<&T>;
59
60 fn downcast_mut(&mut self) -> Option<&mut T>;
71}
72
73macro_rules! impl_downcast_for {
74 ($typ: tt) => {
75 impl_downcast_for!($typ => $typ);
76 };
77 ($($typ: tt)|* => $subtyp: ty) => {
78 #[allow(deprecated)]
79 impl Any<$subtyp> for Packet {
80 fn downcast(self) -> std::result::Result<$subtyp, Packet> {
81 match self {
82 $(Packet::$typ(v) => Ok(v.into()),)*
83 p => Err(p),
84 }
85 }
86
87 fn downcast_ref(&self) -> Option<&$subtyp> {
88 match self {
89 $(Packet::$typ(v) => Some(v.into()),)*
90 _ => None,
91 }
92 }
93
94 fn downcast_mut(&mut self) -> Option<&mut $subtyp> {
95 match self {
96 $(Packet::$typ(v) => Some(v.into()),)*
97 _ => None,
98 }
99 }
100 }
101 };
102}
103
104macro_rules! impl_downcasts {
105 ($($typ:ident, )*) => {
106 $(impl_downcast_for!($typ);)*
107
108 #[allow(unused, deprecated)]
113 fn check_exhaustion(p: Packet) {
114 match p {
115 $(Packet::$typ(_) => (),)*
116 Packet::PublicKey(_) => (),
118 Packet::PublicSubkey(_) => (),
119 Packet::SecretKey(_) => (),
120 Packet::SecretSubkey(_) => (),
121 }
122 }
123 }
124}
125
126impl_downcasts!(
127 Unknown,
128 Signature,
129 OnePassSig,
130 Marker,
131 Trust,
132 UserID,
133 UserAttribute,
134 Literal,
135 CompressedData,
136 PKESK,
137 SKESK,
138 SEIP,
139 MDC,
140 Padding,
141);
142
143impl_downcast_for!(PublicKey | SecretKey
148 => Key<key::PublicParts, key::PrimaryRole>);
149impl_downcast_for!(PublicSubkey | SecretSubkey
150 => Key<key::PublicParts, key::SubordinateRole>);
151impl_downcast_for!(PublicKey | PublicSubkey | SecretKey | SecretSubkey
152 => Key<key::PublicParts, key::UnspecifiedRole>);
153
154impl_downcast_for!(SecretKey
156 => Key<key::SecretParts, key::PrimaryRole>);
157impl_downcast_for!(SecretSubkey
158 => Key<key::SecretParts, key::SubordinateRole>);
159impl_downcast_for!(SecretKey | SecretSubkey
160 => Key<key::SecretParts, key::UnspecifiedRole>);
161
162impl_downcast_for!(PublicKey | SecretKey
164 => Key<key::UnspecifiedParts, key::PrimaryRole>);
165impl_downcast_for!(PublicSubkey | SecretSubkey
166 => Key<key::UnspecifiedParts, key::SubordinateRole>);
167impl_downcast_for!(PublicKey | PublicSubkey | SecretKey | SecretSubkey
168 => Key<key::UnspecifiedParts, key::UnspecifiedRole>);
169
170#[cfg(test)]
171mod test {
172 use super::*;
173
174 #[test]
175 fn downcast() {
176 let p: Packet = Marker::default().into();
177 let mut p = Any::<UserID>::downcast(p).unwrap_err();
178 let r: Option<&UserID> = p.downcast_ref();
179 assert!(r.is_none());
180 let r: Option<&mut UserID> = p.downcast_mut();
181 assert!(r.is_none());
182 let _: &Marker = p.downcast_ref().unwrap();
183 let _: &mut Marker = p.downcast_mut().unwrap();
184 let _: Marker = p.downcast().unwrap();
185 }
186}