summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@sequoia-pgp.org>2024-01-24 09:47:01 +0100
committerNeal H. Walfield <neal@sequoia-pgp.org>2024-01-24 10:16:14 +0100
commit7fefbc950a9fc39437a89443dc5eb8ad824a7bb0 (patch)
tree088bff7aeeb7d8d219d6c8374649228bb825a262
parent8354a954b2b0c25ee142475de88328cb8f49d270 (diff)
openpgp: Add UserID::from_static_bytes, which is constant.
- Add `UserID::from_static_bytes`, which is equivalent to `UserID::from` for a byte slice, but is a constant function.
-rw-r--r--openpgp/NEWS1
-rw-r--r--openpgp/src/packet/mod.rs12
-rw-r--r--openpgp/src/packet/userid.rs40
3 files changed, 47 insertions, 6 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS
index 9b8204f4..d5b7debf 100644
--- a/openpgp/NEWS
+++ b/openpgp/NEWS
@@ -16,6 +16,7 @@
- armor::Reader::from_buffered_reader
- Cert::exportable
- CertBuilder::set_exportable
+ - UserID::from_static_bytes
* Changes in 1.17.0
** Notable fixes
- Sequoia now ignores some formatting errors when reading secret
diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs
index 3a773a3a..68058053 100644
--- a/openpgp/src/packet/mod.rs
+++ b/openpgp/src/packet/mod.rs
@@ -610,6 +610,18 @@ pub struct Common {
}
assert_send_and_sync!(Common);
+impl Common {
+ /// Returns a default version of `Common`.
+ ///
+ /// This is equivalent to using `Common::from`, but the function
+ /// is constant.
+ pub(crate) const fn new() -> Self {
+ Common {
+ dummy: std::marker::PhantomData
+ }
+ }
+}
+
#[cfg(test)]
impl Arbitrary for Common {
fn arbitrary(_: &mut Gen) -> Self {
diff --git a/openpgp/src/packet/userid.rs b/openpgp/src/packet/userid.rs
index 53613d4d..6abc9d5c 100644
--- a/openpgp/src/packet/userid.rs
+++ b/openpgp/src/packet/userid.rs
@@ -472,20 +472,44 @@ pub struct UserID {
/// [RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.11
///
/// Use `UserID::default()` to get a UserID with a default settings.
- value: Vec<u8>,
+ value: Cow<'static, [u8]>,
- hash_algo_security: HashAlgoSecurity,
+ hash_algo_security: OnceCell<HashAlgoSecurity>,
parsed: OnceCell<ConventionallyParsedUserID>,
}
assert_send_and_sync!(UserID);
+impl UserID {
+ /// Returns a User ID.
+ ///
+ /// This is equivalent to using `UserID::from`, but the function
+ /// is constant, and the slice must have a static lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use sequoia_openpgp::packet::UserID;
+ ///
+ /// const TRUST_ROOT_USERID: UserID
+ /// = UserID::from_static_bytes(b"Local Trust Root");
+ /// ```
+ pub const fn from_static_bytes(u: &'static [u8]) -> Self {
+ UserID {
+ common: packet::Common::new(),
+ hash_algo_security: OnceCell::new(),
+ value: Cow::Borrowed(u),
+ parsed: OnceCell::new(),
+ }
+ }
+}
+
impl From<Vec<u8>> for UserID {
fn from(u: Vec<u8>) -> Self {
UserID {
common: Default::default(),
- hash_algo_security: UserID::determine_hash_algo_security(&u),
- value: u,
+ hash_algo_security: Default::default(),
+ value: Cow::Owned(u),
parsed: Default::default(),
}
}
@@ -570,7 +594,7 @@ impl Clone for UserID {
fn clone(&self) -> Self {
UserID {
common: self.common.clone(),
- hash_algo_security: self.hash_algo_security,
+ hash_algo_security: self.hash_algo_security.clone(),
value: self.value.clone(),
parsed: if let Some(p) = self.parsed.get() {
OnceCell::with_value(p.clone())
@@ -729,6 +753,10 @@ impl UserID {
/// [HashAlgoSecurity]: crate::policy::HashAlgoSecurity
pub fn hash_algo_security(&self) -> HashAlgoSecurity {
self.hash_algo_security
+ .get_or_init(|| {
+ UserID::determine_hash_algo_security(&self.value)
+ })
+ .clone()
}
// See documentation for hash_algo_security.
@@ -846,7 +874,7 @@ impl UserID {
/// [`UserID::comment`]: UserID::comment()
/// [conventional User ID]: #conventional-user-ids
pub fn value(&self) -> &[u8] {
- self.value.as_slice()
+ &self.value
}
fn do_parse(&self) -> Result<&ConventionallyParsedUserID> {