summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-10-10 18:57:30 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-10-11 10:20:31 +0200
commitc1a3ab926e4bd4a73b1becdf08b8f4ecb26fc628 (patch)
tree3219b2c5f8df7203ab87bfb91633013be218659c
parent3ec528dd304f65b7d7c0e537920c5b93a4d6b9c0 (diff)
openpgp: Add non-allocating accessors for parsed User ID components.
- Now that we use OnceCell for the cache, we can hand out references to the cached data. This closes the gap between UserID and ConventionallyParsedUserID, hence I think this addresses the concern in #377. - Deprecate the allocating variants. - Fixes #377.
-rw-r--r--autocrypt/src/lib.rs2
-rw-r--r--net/src/lib.rs4
-rw-r--r--net/src/wkd.rs4
-rw-r--r--openpgp/NEWS8
-rw-r--r--openpgp/src/packet/userid.rs43
5 files changed, 52 insertions, 9 deletions
diff --git a/autocrypt/src/lib.rs b/autocrypt/src/lib.rs
index b76c4208..074ecc7d 100644
--- a/autocrypt/src/lib.rs
+++ b/autocrypt/src/lib.rs
@@ -137,7 +137,7 @@ impl AutocryptHeader {
let mut found_one = false;
for uidb in cert.userids().with_policy(policy, None) {
// XXX: Fix match once we have the rfc2822-name-addr.
- if let Ok(Some(a)) = uidb.userid().email() {
+ if let Ok(Some(a)) = uidb.userid().email2() {
if a == addr {
acc.push(uidb.userid().clone().into());
acc.push(uidb.binding_signature().clone().into());
diff --git a/net/src/lib.rs b/net/src/lib.rs
index 60808c8c..750a7bc2 100644
--- a/net/src/lib.rs
+++ b/net/src/lib.rs
@@ -191,7 +191,7 @@ impl KeyServer {
-> Result<Vec<Cert>>
{
let userid = userid.into();
- let email = userid.email().and_then(|addr| addr.ok_or_else(||
+ let email = userid.email2().and_then(|addr| addr.ok_or_else(||
openpgp::Error::InvalidArgument(
"UserID does not contain an email address".into()).into()))?;
let url = self.request_url.join(
@@ -205,7 +205,7 @@ impl KeyServer {
for certo in CertParser::from_bytes(&body)? {
let cert = certo?;
if cert.userids().any(|uid| {
- uid.email().ok()
+ uid.email2().ok()
.and_then(|addro| addro)
.map(|addr| addr == email)
.unwrap_or(false)
diff --git a/net/src/wkd.rs b/net/src/wkd.rs
index ca918733..c1bb0852 100644
--- a/net/src/wkd.rs
+++ b/net/src/wkd.rs
@@ -167,7 +167,7 @@ fn parse_body<S: AsRef<str>>(body: &[u8], email_address: S)
// method to maintain
.filter(|cert| {cert.userids()
.any(|uidb|
- if let Ok(Some(a)) = uidb.userid().email() {
+ if let Ok(Some(a)) = uidb.userid().email2() {
a == email_address
} else { false })
}).cloned().collect();
@@ -244,7 +244,7 @@ pub async fn get<S: AsRef<str>>(c: &reqwest::Client, email_address: S)
fn get_cert_domains<'a>(domain: &'a str, cert: &ValidCert<'a>) -> impl Iterator<Item = Url> + 'a
{
cert.userids().filter_map(move |uidb| {
- uidb.userid().email().unwrap_or(None).and_then(|addr| {
+ uidb.userid().email2().unwrap_or(None).and_then(|addr| {
if EmailAddress::from(&addr).ok().map(|e| e.domain == domain)
.unwrap_or(false)
{
diff --git a/openpgp/NEWS b/openpgp/NEWS
index 926380eb..ceb840f0 100644
--- a/openpgp/NEWS
+++ b/openpgp/NEWS
@@ -44,6 +44,10 @@
- crypto::ecdh::decrypt_unwrap2
- packet::Key::generate_dsa
- packet::Key::generate_elgamal
+ - packet::UserID::comment2
+ - packet::UserID::email2
+ - packet::UserID::name2
+ - packet::UserID::uri2
- parse::PacketParser::start_hashing
- parse::PacketParserBuilder::automatic_hashing
- impl Eq, PartialEq for regex::Regex
@@ -63,6 +67,10 @@
** Deprecated functionality
- cert::Preferences::preferred_aead_algorithms
- crypto::ecdh::decrypt_unwrap
+ - packet::UserID::comment
+ - packet::UserID::email
+ - packet::UserID::name
+ - packet::UserID::uri
- packet::signature::SignatureBuilder::set_preferred_aead_algorithms
- packet::signature::subpacket::SubpacketAreas::preferred_aead_algorithms
- packet::signature::subpacket::SubpacketTag::PreferredAEADAlgorithms
diff --git a/openpgp/src/packet/userid.rs b/openpgp/src/packet/userid.rs
index 1b76a660..1ad272f0 100644
--- a/openpgp/src/packet/userid.rs
+++ b/openpgp/src/packet/userid.rs
@@ -872,6 +872,15 @@ impl UserID {
/// See [conventional User ID] for more information.
///
/// [conventional User ID]: #conventional-user-ids
+ pub fn name2(&self) -> Result<Option<&str>> {
+ Ok(self.do_parse()?.name())
+ }
+
+ /// Parses the User ID according to de facto conventions, and
+ /// returns the name component, if any.
+ ///
+ /// Like [`UserID::name2`], but heap-allocates.
+ #[deprecated(note = "Use UserID::name2")]
pub fn name(&self) -> Result<Option<String>> {
Ok(self.do_parse()?.name().map(|s| s.to_string()))
}
@@ -882,6 +891,15 @@ impl UserID {
/// See [conventional User ID] for more information.
///
/// [conventional User ID]: #conventional-user-ids
+ pub fn comment2(&self) -> Result<Option<&str>> {
+ Ok(self.do_parse()?.comment())
+ }
+
+ /// Parses the User ID according to de facto conventions, and
+ /// returns the comment field, if any.
+ ///
+ /// Like [`UserID::comment2`], but heap-allocates.
+ #[deprecated(note = "Use UserID::comment2")]
pub fn comment(&self) -> Result<Option<String>> {
Ok(self.do_parse()?.comment().map(|s| s.to_string()))
}
@@ -892,6 +910,15 @@ impl UserID {
/// See [conventional User ID] for more information.
///
/// [conventional User ID]: #conventional-user-ids
+ pub fn email2(&self) -> Result<Option<&str>> {
+ Ok(self.do_parse()?.email())
+ }
+
+ /// Parses the User ID according to de facto conventions, and
+ /// returns the email address, if any.
+ ///
+ /// Like [`UserID::email2`], but heap-allocates.
+ #[deprecated(note = "Use UserID::email2")]
pub fn email(&self) -> Result<Option<String>> {
Ok(self.do_parse()?.email().map(|s| s.to_string()))
}
@@ -902,6 +929,15 @@ impl UserID {
/// See [conventional User ID] for more information.
///
/// [conventional User ID]: #conventional-user-ids
+ pub fn uri2(&self) -> Result<Option<&str>> {
+ Ok(self.do_parse()?.uri())
+ }
+
+ /// Parses the User ID according to de facto conventions, and
+ /// returns the URI, if any.
+ ///
+ /// Like [`UserID::uri2`], but heap-allocates.
+ #[deprecated(note = "Use UserID::uri2")]
pub fn uri(&self) -> Result<Option<String>> {
Ok(self.do_parse()?.uri().map(|s| s.to_string()))
}
@@ -925,10 +961,9 @@ impl UserID {
/// [empty locale]: https://www.w3.org/International/wiki/Case_folding
/// [Autocrypt]: https://autocrypt.org/level1.html#e-mail-address-canonicalization
pub fn email_normalized(&self) -> Result<Option<String>> {
- match self.email() {
- e @ Err(_) => e,
- Ok(None) => Ok(None),
- Ok(Some(address)) => {
+ match self.email2()? {
+ None => Ok(None),
+ Some(address) => {
let mut iter = address.split('@');
let localpart = iter.next().expect("Invalid email address");
let domain = iter.next().expect("Invalid email address");