diff options
author | Neal H. Walfield <neal@pep.foundation> | 2022-11-15 00:07:40 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2022-11-15 00:07:40 +0100 |
commit | be2de85d31674b6790b2f02bdac9bf7e7b4810aa (patch) | |
tree | 19fa6d6dd23b335067f014f3bbd2435512d51ade /openpgp/src/types | |
parent | 53474e58493cc10a9e021fde5ca1048a86859f2b (diff) |
openpgp: Add a method to iterate over all variants of some enums.
- It is sometimes useful to iterate over all variants of a
given enum.
- Add the `variants` method to AsymmetricAlgorithm
`PublicKeyAlgorithm`, `SymmetricAlgorithm`, `AEADAlgorithm`,
`CompressionAlgorithm`, `HashAlgorithm`, `SignatureType`,
`ReasonForRevocation`, `DataFormat`, `packet::Tag`, and
`SubpacketTag` to do this.
Diffstat (limited to 'openpgp/src/types')
-rw-r--r-- | openpgp/src/types/mod.rs | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs index f7f615f0..eb57f440 100644 --- a/openpgp/src/types/mod.rs +++ b/openpgp/src/types/mod.rs @@ -127,6 +127,19 @@ pub enum PublicKeyAlgorithm { } assert_send_and_sync!(PublicKeyAlgorithm); +#[allow(deprecated)] +const PUBLIC_KEY_ALGORITHM_VARIANTS: [PublicKeyAlgorithm; 9] = [ + PublicKeyAlgorithm::RSAEncryptSign, + PublicKeyAlgorithm::RSAEncrypt, + PublicKeyAlgorithm::RSASign, + PublicKeyAlgorithm::ElGamalEncrypt, + PublicKeyAlgorithm::DSA, + PublicKeyAlgorithm::ECDH, + PublicKeyAlgorithm::ECDSA, + PublicKeyAlgorithm::ElGamalEncryptSign, + PublicKeyAlgorithm::EdDSA, +]; + impl PublicKeyAlgorithm { /// Returns true if the algorithm can sign data. /// @@ -197,6 +210,15 @@ impl PublicKeyAlgorithm { pub fn is_supported(&self) -> bool { self.is_supported_by_backend() } + + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`PublicKeyAlgorithm::Private`], or + /// [`PublicKeyAlgorithm::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + PUBLIC_KEY_ALGORITHM_VARIANTS.iter().cloned() + } } impl From<u8> for PublicKeyAlgorithm { @@ -658,6 +680,20 @@ pub enum SymmetricAlgorithm { } assert_send_and_sync!(SymmetricAlgorithm); +const SYMMETRIC_ALGORITHM_VARIANTS: [ SymmetricAlgorithm; 11 ] = [ + SymmetricAlgorithm::IDEA, + SymmetricAlgorithm::TripleDES, + SymmetricAlgorithm::CAST5, + SymmetricAlgorithm::Blowfish, + SymmetricAlgorithm::AES128, + SymmetricAlgorithm::AES192, + SymmetricAlgorithm::AES256, + SymmetricAlgorithm::Twofish, + SymmetricAlgorithm::Camellia128, + SymmetricAlgorithm::Camellia192, + SymmetricAlgorithm::Camellia256, +]; + impl Default for SymmetricAlgorithm { fn default() -> Self { SymmetricAlgorithm::AES256 @@ -799,6 +835,18 @@ impl Arbitrary for SymmetricAlgorithm { u8::arbitrary(g).into() } } + +impl SymmetricAlgorithm { + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`SymmetricAlgorithm::Unencrypted`], + /// [`SymmetricAlgorithm::Private`], or + /// [`SymmetricAlgorithm::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + SYMMETRIC_ALGORITHM_VARIANTS.iter().cloned() + } +} /// The AEAD algorithms as defined in [Section 9.6 of RFC 4880bis]. /// @@ -847,6 +895,11 @@ pub enum AEADAlgorithm { } assert_send_and_sync!(AEADAlgorithm); +const AEAD_ALGORITHM_VARIANTS: [AEADAlgorithm; 2] = [ + AEADAlgorithm::EAX, + AEADAlgorithm::OCB, +]; + impl AEADAlgorithm { /// Returns whether this algorithm is supported. /// @@ -861,6 +914,15 @@ impl AEADAlgorithm { pub fn is_supported(&self) -> bool { self.is_supported_by_backend() } + + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`AEADAlgorithm::Private`], or + /// [`AEADAlgorithm::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + AEAD_ALGORITHM_VARIANTS.iter().cloned() + } } impl From<u8> for AEADAlgorithm { @@ -991,6 +1053,13 @@ pub enum CompressionAlgorithm { } assert_send_and_sync!(CompressionAlgorithm); +const COMPRESSION_ALGORITHM_VARIANTS: [CompressionAlgorithm; 4] = [ + CompressionAlgorithm::Uncompressed, + CompressionAlgorithm::Zip, + CompressionAlgorithm::Zlib, + CompressionAlgorithm::BZip2, +]; + impl Default for CompressionAlgorithm { fn default() -> Self { use self::CompressionAlgorithm::*; @@ -1029,6 +1098,15 @@ impl CompressionAlgorithm { _ => false, } } + + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`CompressionAlgorithm::Private`], or + /// [`CompressionAlgorithm::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + COMPRESSION_ALGORITHM_VARIANTS.iter().cloned() + } } impl From<u8> for CompressionAlgorithm { @@ -1124,6 +1202,16 @@ pub enum HashAlgorithm { } assert_send_and_sync!(HashAlgorithm); +const HASH_ALGORITHM_VARIANTS: [HashAlgorithm; 7] = [ + HashAlgorithm::MD5, + HashAlgorithm::SHA1, + HashAlgorithm::RipeMD, + HashAlgorithm::SHA256, + HashAlgorithm::SHA384, + HashAlgorithm::SHA512, + HashAlgorithm::SHA224, +]; + impl Default for HashAlgorithm { fn default() -> Self { // SHA512 is almost twice as fast as SHA256 on 64-bit @@ -1240,6 +1328,15 @@ impl HashAlgorithm { Err(Error::UnsupportedHashAlgorithm(*self).into()), } } + + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`HashAlgorithm::Private`], or + /// [`HashAlgorithm::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + HASH_ALGORITHM_VARIANTS.iter().cloned() + } } #[cfg(test)] @@ -1323,6 +1420,24 @@ pub enum SignatureType { } assert_send_and_sync!(SignatureType); +const SIGNATURE_TYPE_VARIANTS: [SignatureType; 16] = [ + SignatureType::Binary, + SignatureType::Text, + SignatureType::Standalone, + SignatureType::GenericCertification, + SignatureType::PersonaCertification, + SignatureType::CasualCertification, + SignatureType::PositiveCertification, + SignatureType::AttestationKey, + SignatureType::SubkeyBinding, + SignatureType::PrimaryKeyBinding, + SignatureType::DirectKey, + SignatureType::KeyRevocation, + SignatureType::SubkeyRevocation, + SignatureType::CertificationRevocation, + SignatureType::Timestamp, + SignatureType::Confirmation, +]; impl From<u8> for SignatureType { fn from(u: u8) -> Self { @@ -1420,6 +1535,16 @@ impl Arbitrary for SignatureType { } } +impl SignatureType { + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`SignatureType::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + SIGNATURE_TYPE_VARIANTS.iter().cloned() + } +} + /// Describes the reason for a revocation. /// /// See the description of revocation subpackets [Section 5.2.3.23 of RFC 4880]. @@ -1503,6 +1628,14 @@ pub enum ReasonForRevocation { } assert_send_and_sync!(ReasonForRevocation); +const REASON_FOR_REVOCATION_VARIANTS: [ReasonForRevocation; 5] = [ + ReasonForRevocation::Unspecified, + ReasonForRevocation::KeySuperseded, + ReasonForRevocation::KeyCompromised, + ReasonForRevocation::KeyRetired, + ReasonForRevocation::UIDRetired, +]; + impl From<u8> for ReasonForRevocation { fn from(u: u8) -> Self { use self::ReasonForRevocation::*; @@ -1678,6 +1811,15 @@ impl ReasonForRevocation { ReasonForRevocation::Unknown(_) => RevocationType::Hard, } } + + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`ReasonForRevocation::Private`] or + /// [`ReasonForRevocation::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + REASON_FOR_REVOCATION_VARIANTS.iter().cloned() + } } /// Describes the format of the body of a literal data packet. @@ -1742,6 +1884,14 @@ pub enum DataFormat { } assert_send_and_sync!(DataFormat); +#[allow(deprecated)] +const DATA_FORMAT_VARIANTS: [DataFormat; 4] = [ + DataFormat::Binary, + DataFormat::Text, + DataFormat::Unicode, + DataFormat::MIME, +]; + impl Default for DataFormat { fn default() -> Self { DataFormat::Binary @@ -1815,6 +1965,16 @@ impl Arbitrary for DataFormat { } } +impl DataFormat { + /// Returns an iterator over all valid variants. + /// + /// Returns an iterator over all known variants. This does not + /// include the [`DataFormat::Unknown`] variants. + pub fn variants() -> impl Iterator<Item=Self> { + DATA_FORMAT_VARIANTS.iter().cloned() + } +} + /// The revocation status. /// /// # Examples @@ -2107,4 +2267,234 @@ mod tests { } } } + + #[test] + fn public_key_algorithms_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // PUBLIC_KEY_ALGORITHM_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(PublicKeyAlgorithm::from) + .filter(|t| { + match t { + PublicKeyAlgorithm::Private(_) => false, + PublicKeyAlgorithm::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(PUBLIC_KEY_ALGORITHM_VARIANTS.iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn symmetric_algorithms_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // SYMMETRIC_ALGORITHM_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(SymmetricAlgorithm::from) + .filter(|t| { + match t { + SymmetricAlgorithm::Unencrypted => false, + SymmetricAlgorithm::Private(_) => false, + SymmetricAlgorithm::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(SYMMETRIC_ALGORITHM_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn aead_algorithms_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // AEAD_ALGORITHM_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(AEADAlgorithm::from) + .filter(|t| { + match t { + AEADAlgorithm::Private(_) => false, + AEADAlgorithm::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(AEAD_ALGORITHM_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn compression_algorithms_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // COMPRESSION_ALGORITHM_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(CompressionAlgorithm::from) + .filter(|t| { + match t { + CompressionAlgorithm::Private(_) => false, + CompressionAlgorithm::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(COMPRESSION_ALGORITHM_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn hash_algorithms_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // HASH_ALGORITHM_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(HashAlgorithm::from) + .filter(|t| { + match t { + HashAlgorithm::Private(_) => false, + HashAlgorithm::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(HASH_ALGORITHM_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn signature_types_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // SIGNATURE_TYPE_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(SignatureType::from) + .filter(|t| { + match t { + SignatureType::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(SIGNATURE_TYPE_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn reason_for_revocation_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // REASON_FOR_REVOCATION_VARIANTS is a list. Derive it in a + // different way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(ReasonForRevocation::from) + .filter(|t| { + match t { + ReasonForRevocation::Private(_) => false, + ReasonForRevocation::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(REASON_FOR_REVOCATION_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } + + #[test] + fn data_format_variants() { + use std::collections::HashSet; + use std::iter::FromIterator; + + // DATA_FORMAT_VARIANTS is a list. Derive it in a different + // way to double check that nothing is missing. + let derived_variants = (0..=u8::MAX) + .map(DataFormat::from) + .filter(|t| { + match t { + DataFormat::Unknown(_) => false, + _ => true, + } + }) + .collect::<HashSet<_>>(); + + let known_variants + = HashSet::from_iter(DATA_FORMAT_VARIANTS + .iter().cloned()); + + let missing = known_variants + .symmetric_difference(&derived_variants) + .collect::<Vec<_>>(); + + assert!(missing.is_empty(), "{:?}", missing); + } } |