summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2020-05-28 13:57:53 +0200
committerNeal H. Walfield <neal@pep.foundation>2020-06-02 10:40:55 +0200
commitfcdb3fc844e74bb561e0eec82e7abfb7289a2ce0 (patch)
tree165b906070872dcc9dbf4e700608c9ebbedcf558
parentebb719dcc6c0a719cab77f4fb7e296e8efe85f13 (diff)
openpgp: Break up packet::key
- Move the `Key` conversion functions to `packet::key::conversions`.
-rw-r--r--openpgp/src/packet/key.rs415
-rw-r--r--openpgp/src/packet/key/conversions.rs430
2 files changed, 433 insertions, 412 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index 04fa3871..0d9ea96d 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -52,7 +52,7 @@
use std::fmt;
use std::cmp::Ordering;
-use std::convert::{TryFrom, TryInto};
+use std::convert::TryInto;
use std::time;
use quickcheck::{Arbitrary, Gen};
@@ -72,6 +72,8 @@ use crate::KeyID;
use crate::Fingerprint;
use crate::KeyHandle;
+mod conversions;
+
/// A marker trait that indicates whether a `Key` only contains
/// public key material or *may* also contains secret key
/// material.
@@ -383,401 +385,6 @@ pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>;
#[allow(dead_code)]
pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>;
-macro_rules! convert {
- ( $x:ident ) => {
- // XXX: This is ugly, but how can we do better?
- unsafe { std::mem::transmute($x) }
- }
-}
-
-macro_rules! convert_ref {
- ( $x:ident ) => {
- // XXX: This is ugly, but how can we do better?
- unsafe { std::mem::transmute($x) }
- }
-}
-
-// Make it possible to go from an arbitrary Key<P, R> to an
-// arbitrary Key<P', R'> (or &Key<P, R> to &Key<P', R'>) in a
-// single .into().
-//
-// To allow the programmer to make the intent clearer, also
-// provide explicit conversion function.
-
-// In principle, this is as easy as the following:
-//
-// impl<P, P2, R, R2> From<Key<P, R>> for Key<P2, R2>
-// where P: KeyParts, P2: KeyParts, R: KeyRole, R2: KeyRole
-// {
-// fn from(p: Key<P, R>) -> Self {
-// unimplemented!()
-// }
-// }
-//
-// But that results in:
-//
-// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<_, _>>` for type `packet::Key<_, _>`:
-// = note: conflicting implementation in crate `core`:
-// - impl<T> std::convert::From<T> for T;
-//
-// Unfortunately, it's not enough to make one type variable
-// concrete, as the following errors demonstrate:
-//
-// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
-// ...
-// = note: conflicting implementation in crate `core`:
-// - impl<T> std::convert::From<T> for T;
-//
-// impl<P, R, R2> From<Key<P, R>> for Key<PublicParts, R2>
-// where P: KeyParts, R: KeyRole, R2: KeyRole
-// {
-// fn from(p: Key<P, R>) -> Self {
-// unimplemented!()
-// }
-// }
-//
-// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
-// --> openpgp/src/packet/key.rs:186:5
-// ...
-// = note: conflicting implementation in crate `core`:
-// - impl<T> std::convert::From<T> for T;
-// impl<P2, R, R2> From<Key<PublicParts, R>> for Key<P2, R2>
-// where P2: KeyParts, R: KeyRole, R2: KeyRole
-// {
-// fn from(p: Key<PublicParts, R>) -> Self {
-// unimplemented!()
-// }
-// }
-//
-// To solve this, we need at least one generic variable to be
-// concrete on both sides of the `From`.
-
-macro_rules! create_part_conversions {
- ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*>) => {
- create_part_conversions!($Key<$($l),*; $($g),*> where );
- };
- ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*> where $( $w:ident: $c:path ),* ) => {
- // Convert between two KeyParts for a constant KeyRole.
- // Unfortunately, we can't let the KeyRole vary as otherwise we
- // get conflicting types when we do the same to convert between
- // two KeyRoles for a constant KeyParts. :(
- macro_rules! p {
- ( <$from_parts:ty> -> <$to_parts:ty> ) => {
- impl<$($l, )* $($g, )* > From<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
- where $($w: $c ),*
- {
- fn from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
- convert!(p)
- }
- }
-
- impl<$($l, )* $($g, )* > From<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
- where $($w: $c ),*
- {
- fn from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
- convert_ref!(p)
- }
- }
- }
- }
-
- // Likewise, but using TryFrom.
- macro_rules! p_try {
- ( <$from_parts:ty> -> <$to_parts:ty>) => {
- impl<$($l, )* $($g, )* > TryFrom<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
- where $($w: $c ),*
- {
- type Error = anyhow::Error;
- fn try_from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
- p.parts_into_secret()
- }
- }
-
- impl<$($l, )* $($g, )* > TryFrom<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
- where $($w: $c ),*
- {
- type Error = anyhow::Error;
- fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
- if p.has_secret() {
- Ok(convert_ref!(p))
- } else {
- Err(Error::InvalidArgument("No secret key".into())
- .into())
- }
- }
- }
- }
- }
-
-
- p_try!(<PublicParts> -> <SecretParts>);
- p!(<PublicParts> -> <UnspecifiedParts>);
-
- p!(<SecretParts> -> <PublicParts>);
- p!(<SecretParts> -> <UnspecifiedParts>);
-
- p!(<UnspecifiedParts> -> <PublicParts>);
- p_try!(<UnspecifiedParts> -> <SecretParts>);
-
-
- impl<$($l, )* P, $($g, )*> $Key<$($l, )* P, $($g, )*> where P: KeyParts, $($w: $c ),*
- {
- /// Changes the key's parts tag to `PublicParts`.
- pub fn parts_into_public(self) -> $Key<$($l, )* PublicParts, $($g, )*> {
- // Ideally, we'd use self.into() to do the actually
- // conversion. But, because P is not concrete, we get the
- // following error:
- //
- // error[E0277]: the trait bound `packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` is not satisfied
- // --> openpgp/src/packet/key.rs:401:18
- // |
- // 401 | self.into()
- // | ^^^^ the trait `std::convert::From<packet::Key<P, R>>` is not implemented for `packet::Key<packet::key::PublicParts, R>`
- // |
- // = help: consider adding a `where packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` bound
- // = note: required because of the requirements on the impl of `std::convert::Into<packet::Key<packet::key::PublicParts, R>>` for `packet::Key<P, R>`
- //
- // But we can't implement implement `From<Key<P, R>>` for
- // `Key<PublicParts, R>`, because that conflicts with a
- // standard conversion! (See the comment for the `p`
- // macro above.)
- //
- // Adding the trait bound is annoying, because then we'd
- // have to add it everywhere that we use into.
- convert!(self)
- }
-
- /// Changes the key's parts tag to `PublicParts`.
- pub fn parts_as_public(&$($l)* self) -> &$($l)* $Key<$($l, )* PublicParts, $($g, )*> {
- convert_ref!(self)
- }
-
- /// Changes the key's parts tag to `SecretParts`.
- pub fn parts_into_secret(self) -> Result<$Key<$($l, )* SecretParts, $($g, )*>> {
- if self.has_secret() {
- Ok(convert!(self))
- } else {
- Err(Error::InvalidArgument("No secret key".into()).into())
- }
- }
-
- /// Changes the key's parts tag to `SecretParts`.
- pub fn parts_as_secret(&$($l)* self) -> Result<&$($l)* $Key<$($l, )* SecretParts, $($g, )*>>
- {
- if self.has_secret() {
- Ok(convert_ref!(self))
- } else {
- Err(Error::InvalidArgument("No secret key".into()).into())
- }
- }
-
- /// Changes the key's parts tag to `UnspecifiedParts`.
- pub fn parts_into_unspecified(self) -> $Key<$($l, )* UnspecifiedParts, $($g, )*> {
- convert!(self)
- }
-
- /// Changes the key's parts tag to `UnspecifiedParts`.
- pub fn parts_as_unspecified(&$($l)* self) -> &$Key<$($l, )* UnspecifiedParts, $($g, )*> {
- convert_ref!(self)
- }
- }
- }
-}
-
-macro_rules! create_role_conversions {
- ( $Key:ident<$( $l:lifetime ),*> ) => {
- // Convert between two KeyRoles for a constant KeyParts. See
- // the comment for the p macro above.
- macro_rules! r {
- ( <$from_role:ty> -> <$to_role:ty>) => {
- impl<$($l, )* P> From<$Key<$($l, )* P, $from_role>> for $Key<$($l, )* P, $to_role>
- where P: KeyParts
- {
- fn from(p: $Key<$($l, )* P, $from_role>) -> Self {
- convert!(p)
- }
- }
-
- impl<$($l, )* P> From<&$($l)* $Key<$($l, )* P, $from_role>> for &$($l)* $Key<$($l, )* P, $to_role>
- where P: KeyParts
- {
- fn from(p: &$($l)* $Key<$($l, )* P, $from_role>) -> Self {
- convert_ref!(p)
- }
- }
- }
- }
-
- r!(<PrimaryRole> -> <SubordinateRole>);
- r!(<PrimaryRole> -> <UnspecifiedRole>);
-
- r!(<SubordinateRole> -> <PrimaryRole>);
- r!(<SubordinateRole> -> <UnspecifiedRole>);
-
- r!(<UnspecifiedRole> -> <PrimaryRole>);
- r!(<UnspecifiedRole> -> <SubordinateRole>);
- }
-}
-
-macro_rules! create_conversions {
- ( $Key:ident<$( $l:lifetime ),*> ) => {
- create_part_conversions!($Key<$($l ),* ; R> where R: KeyRole);
- create_role_conversions!($Key<$($l ),* >);
-
- // We now handle converting both the part and the role at the same
- // time.
-
- macro_rules! f {
- ( <$from_parts:ty, $from_role:ty> -> <$to_parts:ty, $to_role:ty> ) => {
- impl<$($l ),*> From<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* $to_parts, $to_role>
- {
- fn from(p: $Key<$($l, )* $from_parts, $from_role>) -> Self {
- convert!(p)
- }
- }
-
- impl<$($l ),*> From<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* $to_parts, $to_role>
- {
- fn from(p: &$($l)* $Key<$from_parts, $from_role>) -> Self {
- convert_ref!(p)
- }
- }
- }
- }
-
- // The calls that are comment out are the calls for the
- // combinations where either the KeyParts or the KeyRole does not
- // change.
-
- //f!(<PublicParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
- //f!(<PublicParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
- //f!(<PublicParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
- //f!(<PublicParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
- f!(<PublicParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
- f!(<PublicParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
- //f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
- f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
- f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- //f!(<PublicParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
- //f!(<PublicParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
- //f!(<PublicParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
- f!(<PublicParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
- //f!(<PublicParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
- f!(<PublicParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
- f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
- //f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
- f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
- //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
- //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
- f!(<PublicParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
- f!(<PublicParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
- //f!(<PublicParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
- f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
- f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
- //f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- //f!(<SecretParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
- f!(<SecretParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
- f!(<SecretParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
- //f!(<SecretParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
- //f!(<SecretParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
- //f!(<SecretParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
- //f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
- f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
- f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- f!(<SecretParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
- //f!(<SecretParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
- f!(<SecretParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
- //f!(<SecretParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
- //f!(<SecretParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
- //f!(<SecretParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
- f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
- //f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
- f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- f!(<SecretParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
- f!(<SecretParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
- //f!(<SecretParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
- //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
- //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
- //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
- f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
- f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
- //f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- //f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
- f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
- f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
- //f!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
- f!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
- f!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
- //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
- //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
- //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
- //f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
- f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
- f!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
- //f!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
- f!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
- //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
- //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
- //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
- f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
- f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
- //f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
- f!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
- f!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
- //f!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
- //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
- //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
- //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
-
-
- impl<$($l, )* P, R> $Key<$($l, )* P, R> where P: KeyParts, R: KeyRole
- {
- /// Changes the key's role tag to `PrimaryRole`.
- pub fn role_into_primary(self) -> $Key<$($l, )* P, PrimaryRole> {
- convert!(self)
- }
-
- /// Changes the key's role tag to `PrimaryRole`.
- pub fn role_as_primary(&$($l)* self) -> &$($l)* $Key<$($l, )* P, PrimaryRole> {
- convert_ref!(self)
- }
-
- /// Changes the key's role tag to `SubordinateRole`.
- pub fn role_into_subordinate(self) -> $Key<$($l, )* P, SubordinateRole>
- {
- convert!(self)
- }
-
- /// Changes the key's role tag to `SubordinateRole`.
- pub fn role_as_subordinate(&$($l)* self) -> &$($l)* $Key<$($l, )* P, SubordinateRole>
- {
- convert_ref!(self)
- }
-
- /// Changes the key's role tag to `UnspecifiedRole`.
- pub fn role_into_unspecified(self) -> $Key<$($l, )* P, UnspecifiedRole>
- {
- convert!(self)
- }
-
- /// Changes the key's role tag to `UnspecifiedRole`.
- pub fn role_as_unspecified(&$($l)* self) -> &$($l)* $Key<$($l, )* P, UnspecifiedRole>
- {
- convert_ref!(self)
- }
- }
- }
-}
impl<K: key::KeyParts, R: key::KeyRole> KeyBundle<K, R>
{
@@ -786,22 +393,6 @@ impl<K: key::KeyParts, R: key::KeyRole> KeyBundle<K, R>
}
}
-create_conversions!(Key<>);
-create_conversions!(Key4<>);
-create_conversions!(KeyBundle<>);
-
-// A hack, since the type has to be an ident, which means that we
-// can't use <>.
-type KeyComponentAmalgamation<'a, P, R> = ComponentAmalgamation<'a, Key<P, R>>;
-create_conversions!(KeyComponentAmalgamation<'a>);
-
-create_part_conversions!(PrimaryKeyAmalgamation<'a;>);
-create_part_conversions!(SubordinateKeyAmalgamation<'a;>);
-create_part_conversions!(ErasedKeyAmalgamation<'a;>);
-create_part_conversions!(ValidPrimaryKeyAmalgamation<'a;>);
-create_part_conversions!(ValidSubordinateKeyAmalgamation<'a;>);
-create_part_conversions!(ValidErasedKeyAmalgamation<'a;>);
-
/// Holds a public key, public subkey, private key or private subkey packet.
///
/// See [Section 5.5 of RFC 4880] for details.
diff --git a/openpgp/src/packet/key/conversions.rs b/openpgp/src/packet/key/conversions.rs
new file mode 100644
index 00000000..1665e7c5
--- /dev/null
+++ b/openpgp/src/packet/key/conversions.rs
@@ -0,0 +1,430 @@
+//! Conversion functions for `Key` and associated types.
+
+use std::convert::TryFrom;
+
+use crate::Error;
+use crate::cert::prelude::*;
+use crate::packet::prelude::*;
+use crate::packet::key::{
+ KeyParts,
+ KeyRole,
+ PrimaryRole,
+ PublicParts,
+ SubordinateRole,
+ SecretParts,
+ UnspecifiedParts,
+ UnspecifiedRole
+};
+use crate::Result;
+
+macro_rules! convert {
+ ( $x:ident ) => {
+ // XXX: This is ugly, but how can we do better?
+ unsafe { std::mem::transmute($x) }
+ }
+}
+
+macro_rules! convert_ref {
+ ( $x:ident ) => {
+ // XXX: This is ugly, but how can we do better?
+ unsafe { std::mem::transmute($x) }
+ }
+}
+
+// Make it possible to go from an arbitrary Key<P, R> to an
+// arbitrary Key<P', R'> (or &Key<P, R> to &Key<P', R'>) in a
+// single .into().
+//
+// To allow the programmer to make the intent clearer, also
+// provide explicit conversion function.
+
+// In principle, this is as easy as the following:
+//
+// impl<P, P2, R, R2> From<Key<P, R>> for Key<P2, R2>
+// where P: KeyParts, P2: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<P, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// But that results in:
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<_, _>>` for type `packet::Key<_, _>`:
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+//
+// Unfortunately, it's not enough to make one type variable
+// concrete, as the following errors demonstrate:
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
+// ...
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+//
+// impl<P, R, R2> From<Key<P, R>> for Key<PublicParts, R2>
+// where P: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<P, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
+// --> openpgp/src/packet/key.rs:186:5
+// ...
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+// impl<P2, R, R2> From<Key<PublicParts, R>> for Key<P2, R2>
+// where P2: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<PublicParts, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// To solve this, we need at least one generic variable to be
+// concrete on both sides of the `From`.
+
+macro_rules! create_part_conversions {
+ ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*>) => {
+ create_part_conversions!($Key<$($l),*; $($g),*> where );
+ };
+ ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*> where $( $w:ident: $c:path ),* ) => {
+ // Convert between two KeyParts for a constant KeyRole.
+ // Unfortunately, we can't let the KeyRole vary as otherwise we
+ // get conflicting types when we do the same to convert between
+ // two KeyRoles for a constant KeyParts. :(
+ macro_rules! p {
+ ( <$from_parts:ty> -> <$to_parts:ty> ) => {
+ impl<$($l, )* $($g, )* > From<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ fn from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
+ convert!(p)
+ }
+ }
+
+ impl<$($l, )* $($g, )* > From<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ fn from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
+ convert_ref!(p)
+ }
+ }
+ }
+ }
+
+ // Likewise, but using TryFrom.
+ macro_rules! p_try {
+ ( <$from_parts:ty> -> <$to_parts:ty>) => {
+ impl<$($l, )* $($g, )* > TryFrom<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ type Error = anyhow::Error;
+ fn try_from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
+ p.parts_into_secret()
+ }
+ }
+
+ impl<$($l, )* $($g, )* > TryFrom<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ type Error = anyhow::Error;
+ fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
+ if p.has_secret() {
+ Ok(convert_ref!(p))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into())
+ .into())
+ }
+ }
+ }
+ }
+ }
+
+
+ p_try!(<PublicParts> -> <SecretParts>);
+ p!(<PublicParts> -> <UnspecifiedParts>);
+
+ p!(<SecretParts> -> <PublicParts>);
+ p!(<SecretParts> -> <UnspecifiedParts>);
+
+ p!(<UnspecifiedParts> -> <PublicParts>);
+ p_try!(<UnspecifiedParts> -> <SecretParts>);
+
+
+ impl<$($l, )* P, $($g, )*> $Key<$($l, )* P, $($g, )*> where P: KeyParts, $($w: $c ),*
+ {
+ /// Changes the key's parts tag to `PublicParts`.
+ pub fn parts_into_public(self) -> $Key<$($l, )* PublicParts, $($g, )*> {
+ // Ideally, we'd use self.into() to do the actually
+ // conversion. But, because P is not concrete, we get the
+ // following error:
+ //
+ // error[E0277]: the trait bound `packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` is not satisfied
+ // --> openpgp/src/packet/key.rs:401:18
+ // |
+ // 401 | self.into()
+ // | ^^^^ the trait `std::convert::From<packet::Key<P, R>>` is not implemented for `packet::Key<packet::key::PublicParts, R>`
+ // |
+ // = help: consider adding a `where packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` bound
+ // = note: required because of the requirements on the impl of `std::convert::Into<packet::Key<packet::key::PublicParts, R>>` for `packet::Key<P, R>`
+ //
+ // But we can't implement implement `From<Key<P, R>>` for
+ // `Key<PublicParts, R>`, because that conflicts with a
+ // standard conversion! (See the comment for the `p`
+ // macro above.)
+ //
+ // Adding the trait bound is annoying, because then we'd
+ // have to add it everywhere that we use into.
+ convert!(self)
+ }
+
+ /// Changes the key's parts tag to `PublicParts`.
+ pub fn parts_as_public(&$($l)* self) -> &$($l)* $Key<$($l, )* PublicParts, $($g, )*> {
+ convert_ref!(self)
+ }