summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAzul <azul@riseup.net>2020-10-09 20:05:33 +0200
committerAzul <azul@riseup.net>2020-10-26 17:47:09 +0100
commitd662a80e8f7c96b72708e4124546f72d2712ed40 (patch)
treebeb51cb910bdb1448e4a3edfe4059dca78eb7e8e
parent3fc8654d33c8c57542250eda8e910a2ffa0b8a81 (diff)
openpgp: seal the Preferences trait
[Seal] the `cert::Preferences` trait so it cannot be implemented for types outside this crate. Therefore it can be extended in a non-breaking way. Attempts to implement the trait will not compile. refers: #538 [seal]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
-rw-r--r--openpgp/src/cert.rs13
-rw-r--r--openpgp/src/cert/amalgamation.rs2
-rw-r--r--openpgp/src/lib.rs1
-rw-r--r--openpgp/src/seal.rs46
4 files changed, 60 insertions, 2 deletions
diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs
index bcfd79be..abcc3ae5 100644
--- a/openpgp/src/cert.rs
+++ b/openpgp/src/cert.rs
@@ -437,8 +437,15 @@ type UnknownBundles = ComponentBundles<Unknown>;
/// # Ok(()) }
/// ```
///
-/// [Section 5.2.3.3]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
-pub trait Preferences<'a> {
+/// # Sealed trait
+///
+/// This trait is [sealed] and cannot be implemented for types outside this crate.
+/// Therefore it can be extended in a non-breaking way.
+/// If you want to implement the trait inside the crate
+/// you also need to implement the `seal::Sealed` marker trait.
+///
+/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
+pub trait Preferences<'a>: crate::seal::Sealed {
/// Returns the supported symmetric algorithms ordered by
/// preference.
///
@@ -2787,6 +2794,8 @@ pub struct ValidCert<'a> {
time: time::SystemTime,
}
+impl<'a> crate::seal::Sealed for ValidCert<'a> {}
+
impl<'a> std::ops::Deref for ValidCert<'a> {
type Target = Cert;
diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs
index def67a4d..3d4602bc 100644
--- a/openpgp/src/cert/amalgamation.rs
+++ b/openpgp/src/cert/amalgamation.rs
@@ -1057,6 +1057,8 @@ pub struct ValidComponentAmalgamation<'a, C> {
binding_signature: &'a Signature,
}
+impl<'a, C> crate::seal::Sealed for ValidComponentAmalgamation<'a, C> {}
+
/// A Valid User ID and its associated data.
///
/// A specialized version of [`ValidComponentAmalgamation`].
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index cce9ad6e..d71bb483 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -152,6 +152,7 @@ mod keyhandle;
pub use keyhandle::KeyHandle;
pub mod policy;
+pub(crate) mod seal;
pub(crate) mod utils;
#[cfg(test)]
diff --git a/openpgp/src/seal.rs b/openpgp/src/seal.rs
new file mode 100644
index 00000000..bfdbd1e4
--- /dev/null
+++ b/openpgp/src/seal.rs
@@ -0,0 +1,46 @@
+//! [Sealing Traits]
+//!
+//! [sealing traits:] https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
+//!
+//! Prevent the implementation of traits outside of the crate
+//! to allow extension of the traits at a later time.
+//!
+//! Mark a trait as sealed by deriving it from seal::Sealed.
+//!
+//! Only Implementations of seal::Sealed will be able to implement the trait.
+//! Since seal::Sealed is only visible inside the crate
+//! sealed traits can only be implemented in the crate.
+
+/// This trait is used to [seal] other traits so they cannot
+/// be implemented for types outside this crate.
+/// Therefore they can be extended in a non-breaking way.
+///
+/// [seal]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
+///
+/// # Examples
+///
+/// For example the [`cert::Preferences`] trait is sealed.
+/// Therefore attempts to implement it will not compile:
+///
+/// [`cert::Preferences`]: ../cert/trait.Preferences.html
+///
+/// ```compile_fail
+/// # extern crate sequoia_openpgp as openpgp;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::cert::Preferences;
+/// use openpgp::types::*;
+///
+/// pub struct InvalidComponentAmalgamation {}
+/// impl<'a> Preferences<'a> for InvalidComponentAmalgamation { //~ ERROR `_x @` is not allowed in a tuple
+/// fn preferred_symmetric_algorithms(&self)
+/// -> Option<&'a [SymmetricAlgorithm]> { None }
+/// fn preferred_hash_algorithms(&self) -> Option<&'a [HashAlgorithm]> { None }
+/// fn preferred_compression_algorithms(&self)
+/// -> Option<&'a [CompressionAlgorithm]> { None }
+/// fn preferred_aead_algorithms(&self) -> Option<&'a [AEADAlgorithm]> { None }
+/// fn key_server_preferences(&self) -> Option<KeyServerPreferences> { None }
+/// fn preferred_key_server(&self) -> Option<&'a [u8]> { None }
+/// fn features(&self) -> Option<Features> { None }
+/// }
+/// ```
+pub trait Sealed {}