diff --git a/crates/common/src/addresses.rs b/crates/common/src/addresses.rs index 5f67a4b6..f94f4433 100644 --- a/crates/common/src/addresses.rs +++ b/crates/common/src/addresses.rs @@ -4,10 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::borrow::Cow; - -use compact_str::CompactString; use directory::{Directory, backend::RcptType}; +use std::borrow::Cow; use utils::config::{Config, utils::AsKey}; use crate::{ @@ -100,7 +98,7 @@ impl Server { directory: &Directory, address: &str, session_id: u64, - ) -> trc::Result> { + ) -> trc::Result> { directory .vrfy( self.core @@ -120,7 +118,7 @@ impl Server { directory: &Directory, address: &str, session_id: u64, - ) -> trc::Result> { + ) -> trc::Result> { directory .expn( self.core @@ -196,7 +194,7 @@ impl AddressMapping { } AddressMapping::Custom(if_block) => { if let Some(result) = core - .eval_if::(if_block, &Address(address), session_id) + .eval_if::(if_block, &Address(address), session_id) .await { return result.into(); @@ -220,9 +218,9 @@ impl AddressMapping { .map(|(_, domain_part)| format!("@{}", domain_part)) .map(Cow::Owned), AddressMapping::Custom(if_block) => core - .eval_if::(if_block, &Address(address), session_id) + .eval_if::(if_block, &Address(address), session_id) .await - .map(|s| Cow::Owned(s.into())), + .map(Cow::Owned), AddressMapping::Disable => None, } } diff --git a/crates/common/src/auth/mod.rs b/crates/common/src/auth/mod.rs index 81f6e7b9..6db82787 100644 --- a/crates/common/src/auth/mod.rs +++ b/crates/common/src/auth/mod.rs @@ -6,7 +6,7 @@ use std::{net::IpAddr, sync::Arc}; -use compact_str::CompactString; + use directory::{ Directory, Permission, Permissions, Principal, QueryBy, core::secret::verify_secret_hash, }; @@ -31,9 +31,9 @@ pub struct AccessToken { pub primary_id: u32, pub member_of: Vec, pub access_to: VecMap>, - pub name: CompactString, - pub description: Option, - pub emails: Vec, + pub name: String, + pub description: Option, + pub emails: Vec, pub quota: u64, pub permissions: Permissions, pub tenant: Option, diff --git a/crates/common/src/auth/oauth/introspect.rs b/crates/common/src/auth/oauth/introspect.rs index ca5161bd..ab81eb57 100644 --- a/crates/common/src/auth/oauth/introspect.rs +++ b/crates/common/src/auth/oauth/introspect.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use serde::{Deserialize, Serialize}; use trc::{AddContext, AuthEvent, EventType}; @@ -17,19 +17,19 @@ pub struct OAuthIntrospect { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub scope: Option, + pub scope: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub client_id: Option, + pub client_id: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub username: Option, + pub username: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub token_type: Option, + pub token_type: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -45,7 +45,7 @@ pub struct OAuthIntrospect { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub sub: Option, + pub sub: Option, } impl Server { diff --git a/crates/common/src/auth/oauth/oidc.rs b/crates/common/src/auth/oauth/oidc.rs index c1385793..e3676e7f 100644 --- a/crates/common/src/auth/oauth/oidc.rs +++ b/crates/common/src/auth/oauth/oidc.rs @@ -7,7 +7,7 @@ use std::fmt; use biscuit::{ClaimsSet, JWT, RegisteredClaims, SingleOrMultiple, jws::RegisteredHeader}; -use compact_str::CompactString; + use serde::{ Deserialize, Deserializer, Serialize, de::{self, Visitor}, @@ -20,47 +20,47 @@ use crate::Server; pub struct Userinfo { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub sub: Option, + pub sub: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, + pub name: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub given_name: Option, + pub given_name: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub family_name: Option, + pub family_name: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub middle_name: Option, + pub middle_name: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub nickname: Option, + pub nickname: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub preferred_username: Option, + pub preferred_username: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub profile: Option, + pub profile: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub picture: Option, + pub picture: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub website: Option, + pub website: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub email: Option, + pub email: Option, #[serde(default, deserialize_with = "any_bool")] #[serde(skip_serializing_if = "std::ops::Not::not")] @@ -68,11 +68,11 @@ pub struct Userinfo { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub zoneinfo: Option, + pub zoneinfo: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub locale: Option, + pub locale: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -83,15 +83,15 @@ pub struct Userinfo { pub struct StandardClaims { #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] - pub nonce: Option, + pub nonce: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] - pub preferred_username: Option, + pub preferred_username: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] - pub email: Option, + pub email: Option, } impl Server { diff --git a/crates/common/src/auth/oauth/registration.rs b/crates/common/src/auth/oauth/registration.rs index 0f93a889..6a0b0adf 100644 --- a/crates/common/src/auth/oauth/registration.rs +++ b/crates/common/src/auth/oauth/registration.rs @@ -4,22 +4,22 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug, Default)] #[serde(rename_all = "snake_case")] pub struct ClientRegistrationRequest { - pub redirect_uris: Vec, + pub redirect_uris: Vec, #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub response_types: Vec, + pub response_types: Vec, #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub grant_types: Vec, + pub grant_types: Vec, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -27,31 +27,31 @@ pub struct ClientRegistrationRequest { #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub contacts: Vec, + pub contacts: Vec, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub client_name: Option, + pub client_name: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub logo_uri: Option, + pub logo_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub client_uri: Option, + pub client_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub policy_uri: Option, + pub policy_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub tos_uri: Option, + pub tos_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub jwks_uri: Option, + pub jwks_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -59,7 +59,7 @@ pub struct ClientRegistrationRequest { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub sector_identifier_uri: Option, + pub sector_identifier_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -67,39 +67,39 @@ pub struct ClientRegistrationRequest { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub id_token_signed_response_alg: Option, + pub id_token_signed_response_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub id_token_encrypted_response_alg: Option, + pub id_token_encrypted_response_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub id_token_encrypted_response_enc: Option, + pub id_token_encrypted_response_enc: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub userinfo_signed_response_alg: Option, + pub userinfo_signed_response_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub userinfo_encrypted_response_alg: Option, + pub userinfo_encrypted_response_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub userinfo_encrypted_response_enc: Option, + pub userinfo_encrypted_response_enc: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub request_object_signing_alg: Option, + pub request_object_signing_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub request_object_encryption_alg: Option, + pub request_object_encryption_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub request_object_encryption_enc: Option, + pub request_object_encryption_enc: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -107,7 +107,7 @@ pub struct ClientRegistrationRequest { #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub token_endpoint_auth_signing_alg: Option, + pub token_endpoint_auth_signing_alg: Option, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -119,34 +119,34 @@ pub struct ClientRegistrationRequest { #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub default_acr_values: Vec, + pub default_acr_values: Vec, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - pub initiate_login_uri: Option, + pub initiate_login_uri: Option, #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub request_uris: Vec, + pub request_uris: Vec, #[serde(flatten)] #[serde(skip_serializing_if = "HashMap::is_empty")] - pub additional_fields: HashMap, + pub additional_fields: HashMap, } #[derive(Serialize, Deserialize, Debug, Default)] #[serde(rename_all = "snake_case")] pub struct ClientRegistrationResponse { // Required fields - pub client_id: CompactString, + pub client_id: String, // Optional fields specific to the response #[serde(skip_serializing_if = "Option::is_none")] - pub client_secret: Option, + pub client_secret: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub registration_access_token: Option, + pub registration_access_token: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub registration_client_uri: Option, + pub registration_client_uri: Option, #[serde(skip_serializing_if = "Option::is_none")] pub client_id_issued_at: Option, #[serde(skip_serializing_if = "Option::is_none")] diff --git a/crates/common/src/auth/oauth/token.rs b/crates/common/src/auth/oauth/token.rs index 4cdf2b10..0f33c9e3 100644 --- a/crates/common/src/auth/oauth/token.rs +++ b/crates/common/src/auth/oauth/token.rs @@ -6,7 +6,7 @@ use std::time::SystemTime; -use compact_str::CompactString; + use directory::QueryBy; use mail_builder::encoders::base64::base64_encode; use mail_parser::decoders::base64::base64_decode; @@ -24,7 +24,7 @@ use super::{CLIENT_ID_MAX_LEN, GrantType, RANDOM_CODE_LEN, crypto::SymmetricEncr pub struct TokenInfo { pub grant_type: GrantType, pub account_id: u32, - pub client_id: CompactString, + pub client_id: String, pub expiry: u64, pub issued_at: u64, pub expires_in: u64, @@ -128,7 +128,7 @@ impl Server { GrantType::from_id(bytes.next().copied()?)?, bytes.next_leb128::()?, bytes.next_leb128::()?, - bytes.copied().map(char::from).collect::(), + bytes.copied().map(char::from).collect::(), ) .into() }) @@ -216,7 +216,7 @@ impl Server { }) } - pub async fn password_hash(&self, account_id: u32) -> trc::Result { + pub async fn password_hash(&self, account_id: u32) -> trc::Result { if account_id != u32::MAX { self.core .storage diff --git a/crates/common/src/config/network.rs b/crates/common/src/config/network.rs index 294df513..78b63cce 100644 --- a/crates/common/src/config/network.rs +++ b/crates/common/src/config/network.rs @@ -8,7 +8,7 @@ use std::time::Duration; use crate::expr::{if_block::IfBlock, tokenizer::TokenMap}; use ahash::AHashSet; -use compact_str::CompactString; + use utils::config::{Config, Rate}; use super::*; @@ -17,8 +17,8 @@ use super::*; pub struct Network { pub node_id: u64, pub roles: ClusterRoles, - pub server_name: CompactString, - pub report_domain: CompactString, + pub server_name: String, + pub report_domain: String, pub security: Security, pub contact_form: Option, pub http_response_url: IfBlock, @@ -28,14 +28,14 @@ pub struct Network { #[derive(Clone)] pub struct ContactForm { - pub rcpt_to: Vec, + pub rcpt_to: Vec, pub max_size: usize, pub rate: Option, pub validate_domain: bool, pub from_email: FieldOrDefault, pub from_subject: FieldOrDefault, pub from_name: FieldOrDefault, - pub field_honey_pot: Option, + pub field_honey_pot: Option, } #[derive(Clone)] @@ -129,7 +129,7 @@ impl ContactForm { .values("form.deliver-to") .filter_map(|(_, addr)| { if addr.contains('@') && addr.contains('.') { - Some(CompactString::from_str_to_lowercase(addr.trim())) + Some(addr.trim().to_lowercase()) } else { None } @@ -200,8 +200,8 @@ impl Network { let mut network = Network { node_id: config.property("cluster.node-id").unwrap_or(1), - report_domain: report_domain.into(), - server_name: server_name.into(), + report_domain, + server_name, security: Security::parse(config), contact_form: ContactForm::parse(config), asn_geo_lookup: AsnGeoLookupConfig::parse(config).unwrap_or_default(), diff --git a/crates/common/src/config/smtp/session.rs b/crates/common/src/config/smtp/session.rs index ac5d5889..4a605d2f 100644 --- a/crates/common/src/config/smtp/session.rs +++ b/crates/common/src/config/smtp/session.rs @@ -12,7 +12,7 @@ use std::{ use ahash::AHashSet; use base64::{Engine, engine::general_purpose::STANDARD}; -use compact_str::CompactString; + use hyper::{ HeaderMap, header::{AUTHORIZATION, CONTENT_TYPE, HeaderName, HeaderValue}, @@ -143,9 +143,9 @@ pub struct Data { #[derive(Clone)] pub struct Milter { pub enable: IfBlock, - pub id: Arc, + pub id: Arc, pub addrs: Vec, - pub hostname: CompactString, + pub hostname: String, pub port: u16, pub timeout_connect: Duration, pub timeout_command: Duration, @@ -473,7 +473,7 @@ fn parse_milter(config: &mut Config, id: &str, token_map: &TokenMap) -> Option Option { + fn default_logo_url(&self) -> Option { self.core .enterprise .as_ref() diff --git a/crates/common/src/expr/eval.rs b/crates/common/src/expr/eval.rs index 5eb5853b..c750b60d 100644 --- a/crates/common/src/expr/eval.rs +++ b/crates/common/src/expr/eval.rs @@ -701,6 +701,21 @@ impl<'x> TryFrom> for CompactString { } } +impl<'x> TryFrom> for String { + type Error = (); + + fn try_from(value: Variable<'x>) -> Result { + if let Variable::String(s) = value { + Ok(match s { + StringCow::Borrowed(v) => v.to_string(), + StringCow::Owned(v) => v.into_string(), + }) + } else { + Err(()) + } + } +} + impl<'x> From> for bool { fn from(val: Variable<'x>) -> Self { val.to_bool() diff --git a/crates/common/src/expr/if_block.rs b/crates/common/src/expr/if_block.rs index ae91cc6f..37fd4e20 100644 --- a/crates/common/src/expr/if_block.rs +++ b/crates/common/src/expr/if_block.rs @@ -23,14 +23,14 @@ pub struct IfThen { #[derive(Debug, Clone, PartialEq, Eq)] pub struct IfBlock { - pub key: CompactString, + pub key: String, pub if_then: Vec, pub default: Expression, } impl IfBlock { pub fn new( - key: impl Into, + key: impl Into, if_thens: impl IntoIterator, default: impl AsRef, ) -> Self { @@ -51,7 +51,7 @@ impl IfBlock { } } - pub fn empty(key: impl Into) -> Self { + pub fn empty(key: impl Into) -> Self { Self { key: key.into(), if_then: Default::default(), @@ -102,7 +102,7 @@ impl IfBlock { // Parse conditions let mut if_block = IfBlock { - key: key.into(), + key, if_then: Default::default(), default: Expression { items: Default::default(), @@ -214,7 +214,7 @@ impl IfBlock { } } - pub fn into_default(self, key: impl Into) -> IfBlock { + pub fn into_default(self, key: impl Into) -> IfBlock { IfBlock { key: key.into(), if_then: Default::default(), diff --git a/crates/common/src/ipc.rs b/crates/common/src/ipc.rs index 37245340..7853596e 100644 --- a/crates/common/src/ipc.rs +++ b/crates/common/src/ipc.rs @@ -7,7 +7,6 @@ use std::{sync::Arc, time::Instant}; use ahash::RandomState; -use compact_str::CompactString; use jmap_proto::types::{state::StateChange, type_state::DataType}; use mail_auth::{ dmarc::Dmarc, @@ -70,8 +69,8 @@ pub enum StateEvent { pub enum UpdateSubscription { Unverified { id: u32, - url: CompactString, - code: CompactString, + url: String, + code: String, keys: Option, }, Verified(PushSubscription), @@ -80,7 +79,7 @@ pub enum UpdateSubscription { #[derive(Debug)] pub struct PushSubscription { pub id: u32, - pub url: CompactString, + pub url: String, pub expires: u64, pub types: Bitmap, pub keys: Option, diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 287c397a..34b19e9b 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -19,7 +19,6 @@ use std::{ use ahash::{AHashMap, AHashSet}; use arc_swap::ArcSwap; use auth::{AccessToken, oauth::config::OAuthConfig, roles::RolePermissions}; -use compact_str::CompactString; use config::{ dav::DavConfig, imap::ImapConfig, @@ -180,7 +179,7 @@ pub struct MessageStoreCache { pub change_id: u64, pub items: Vec, pub index: AHashMap, - pub keywords: Vec, + pub keywords: Vec, pub update_lock: Arc, pub size: u64, } @@ -203,8 +202,8 @@ pub struct MessageUidCache { #[derive(Debug, Clone)] pub struct MailboxCache { pub document_id: u32, - pub name: CompactString, - pub path: CompactString, + pub name: String, + pub path: String, pub role: SpecialUse, pub parent_id: u32, pub sort_order: u32, diff --git a/crates/common/src/listener/acme/order.rs b/crates/common/src/listener/acme/order.rs index ba5bdb0c..074f9e06 100644 --- a/crates/common/src/listener/acme/order.rs +++ b/crates/common/src/listener/acme/order.rs @@ -1,6 +1,7 @@ // Adapted from rustls-acme (https://github.com/FlorianUekermann/rustls-acme), licensed under MIT/Apache-2.0. use chrono::{DateTime, TimeZone, Utc}; + use compact_str::CompactString; use dns_update::DnsRecord; use futures::future::try_join_all; diff --git a/crates/common/src/scripts/mod.rs b/crates/common/src/scripts/mod.rs index b815f99c..60602e12 100644 --- a/crates/common/src/scripts/mod.rs +++ b/crates/common/src/scripts/mod.rs @@ -6,7 +6,7 @@ use std::sync::Arc; -use compact_str::CompactString; + use sieve::{Envelope, runtime::Variable}; use store::Value; use unicode_security::mixed_script::AugmentedScriptSet; @@ -22,7 +22,7 @@ pub mod plugins; pub enum ScriptModification { SetEnvelope { name: Envelope, - value: CompactString, + value: String, }, AddHeader { name: Arc, diff --git a/crates/common/src/sharing/acl.rs b/crates/common/src/sharing/acl.rs index 07998efa..d9c22bea 100644 --- a/crates/common/src/sharing/acl.rs +++ b/crates/common/src/sharing/acl.rs @@ -101,7 +101,7 @@ impl Server { .unwrap_or_default() { acl_obj.append( - Property::_T(name.into()), + Property::_T(name), item.grants .map(|acl_item| Value::Text(acl_item.to_string())) .collect::>(), diff --git a/crates/dav/src/common/acl.rs b/crates/dav/src/common/acl.rs index 88f5d50e..f30a3a9f 100644 --- a/crates/dav/src/common/acl.rs +++ b/crates/dav/src/common/acl.rs @@ -493,7 +493,7 @@ impl DavAclHandler for Server { .get_principal_name(grant_account_id) .await .caused_by(trc::location!())? - .unwrap_or_else(|| format_compact!("_{grant_account_id}")); + .unwrap_or_else(|| format!("_{grant_account_id}")); aces.push(Ace::new( Principal::Href(Href(format!( diff --git a/crates/dav/src/principal/propfind.rs b/crates/dav/src/principal/propfind.rs index bb3e2bcf..8ca22940 100644 --- a/crates/dav/src/principal/propfind.rs +++ b/crates/dav/src/principal/propfind.rs @@ -294,7 +294,7 @@ impl PrincipalPropFind for Server { .get_principal_name(account_id) .await .caused_by(trc::location!())? - .unwrap_or_else(|| format_compact!("_{account_id}")); + .unwrap_or_else(|| format!("_{account_id}")); Ok(Href(format!( "{}/{}", DavResource::Principal.base_path(), diff --git a/crates/directory/src/backend/imap/lookup.rs b/crates/directory/src/backend/imap/lookup.rs index d71f0dc5..1806246a 100644 --- a/crates/directory/src/backend/imap/lookup.rs +++ b/crates/directory/src/backend/imap/lookup.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use mail_send::Credentials; use smtp_proto::{AUTH_CRAM_MD5, AUTH_LOGIN, AUTH_OAUTHBEARER, AUTH_PLAIN, AUTH_XOAUTH2}; @@ -69,11 +69,11 @@ impl ImapDirectory { Err(trc::StoreEvent::NotSupported.caused_by(trc::location!())) } - pub async fn vrfy(&self, _address: &str) -> trc::Result> { + pub async fn vrfy(&self, _address: &str) -> trc::Result> { Err(trc::StoreEvent::NotSupported.caused_by(trc::location!())) } - pub async fn expn(&self, _address: &str) -> trc::Result> { + pub async fn expn(&self, _address: &str) -> trc::Result> { Err(trc::StoreEvent::NotSupported.caused_by(trc::location!())) } diff --git a/crates/directory/src/backend/internal/lookup.rs b/crates/directory/src/backend/internal/lookup.rs index 87ceb241..24305ba3 100644 --- a/crates/directory/src/backend/internal/lookup.rs +++ b/crates/directory/src/backend/internal/lookup.rs @@ -6,7 +6,7 @@ use super::{PrincipalInfo, manage::ManageDirectory}; use crate::{Principal, PrincipalData, QueryBy, Type, backend::RcptType}; -use compact_str::CompactString; + use mail_send::Credentials; use store::{ Deserialize, IterateParams, Store, ValueKey, @@ -24,9 +24,9 @@ pub trait DirectoryStore: Sync + Send { async fn email_to_id(&self, address: &str) -> trc::Result>; async fn is_local_domain(&self, domain: &str) -> trc::Result; async fn rcpt(&self, address: &str) -> trc::Result; - async fn vrfy(&self, address: &str) -> trc::Result>; - async fn expn(&self, address: &str) -> trc::Result>; - async fn expn_by_id(&self, id: u32) -> trc::Result>; + async fn vrfy(&self, address: &str) -> trc::Result>; + async fn expn(&self, address: &str) -> trc::Result>; + async fn expn_by_id(&self, id: u32) -> trc::Result>; } impl DirectoryStore for Store { @@ -123,7 +123,7 @@ impl DirectoryStore for Store { } } - async fn vrfy(&self, address: &str) -> trc::Result> { + async fn vrfy(&self, address: &str) -> trc::Result> { let mut results = Vec::new(); let address = address.split('@').next().unwrap_or(address); if address.len() > 3 { @@ -155,7 +155,7 @@ impl DirectoryStore for Store { Ok(results) } - async fn expn(&self, address: &str) -> trc::Result> { + async fn expn(&self, address: &str) -> trc::Result> { if let Some(ptype) = self .get_value::(ValueKey::from(ValueClass::Directory( DirectoryClass::EmailToId(address.as_bytes().to_vec()), @@ -169,7 +169,7 @@ impl DirectoryStore for Store { } } - async fn expn_by_id(&self, list_id: u32) -> trc::Result> { + async fn expn_by_id(&self, list_id: u32) -> trc::Result> { let mut results = Vec::new(); for account_id in self.get_members(list_id).await? { if let Some(email) = self diff --git a/crates/directory/src/backend/internal/manage.rs b/crates/directory/src/backend/internal/manage.rs index 791f5d42..2ad14fee 100644 --- a/crates/directory/src/backend/internal/manage.rs +++ b/crates/directory/src/backend/internal/manage.rs @@ -13,6 +13,7 @@ use crate::{ QueryBy, ROLE_ADMIN, ROLE_TENANT_ADMIN, ROLE_USER, Type, backend::RcptType, }; use ahash::{AHashMap, AHashSet}; + use compact_str::CompactString; use jmap_proto::types::collection::Collection; use store::{ @@ -61,7 +62,7 @@ pub trait ManageDirectory: Sized { async fn get_principal_info(&self, name: &str) -> trc::Result>; async fn get_or_create_principal_id(&self, name: &str, typ: Type) -> trc::Result; async fn get_principal(&self, principal_id: u32) -> trc::Result>; - async fn get_principal_name(&self, principal_id: u32) -> trc::Result>; + async fn get_principal_name(&self, principal_id: u32) -> trc::Result>; async fn get_member_of(&self, principal_id: u32) -> trc::Result>; async fn get_members(&self, principal_id: u32) -> trc::Result>; async fn create_principal( @@ -125,7 +126,7 @@ impl ManageDirectory for Store { } } - async fn get_principal_name(&self, principal_id: u32) -> trc::Result> { + async fn get_principal_name(&self, principal_id: u32) -> trc::Result> { let archive = self .get_value::>(ValueKey::from(ValueClass::Directory( DirectoryClass::Principal(principal_id), @@ -248,11 +249,11 @@ impl ManageDirectory for Store { allowed_permissions: Option<&Permissions>, ) -> trc::Result { // Make sure the principal has a name - let name = CompactString::from_str_to_lowercase(principal_set.name()); + let name = principal_set.name().to_lowercase(); if name.is_empty() { return Err(err_missing(PrincipalField::Name)); } - let mut valid_domains: AHashSet = AHashSet::new(); + let mut valid_domains: AHashSet = AHashSet::new(); // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd @@ -1271,7 +1272,7 @@ impl ManageDirectory for Store { PrincipalValue::String(email), ) => { let email = email.to_lowercase(); - if let Some(idx) = principal.emails.iter().position(|v| v == email) { + if let Some(idx) = principal.emails.iter().position(|v| v == &email) { principal.emails.remove(idx); batch.clear(ValueClass::Directory(DirectoryClass::EmailToId( email.as_bytes().to_vec(), @@ -1899,7 +1900,7 @@ impl ManageDirectory for Store { { let mut principal = Principal::new(pt.id, pt.typ); principal.name = - CompactString::from_utf8_lossy(key.get(1..).unwrap_or_default()); + String::from_utf8_lossy(key.get(1..).unwrap_or_default()).into_owned(); results.push(principal); } diff --git a/crates/directory/src/backend/internal/mod.rs b/crates/directory/src/backend/internal/mod.rs index 8e371041..4c608af6 100644 --- a/crates/directory/src/backend/internal/mod.rs +++ b/crates/directory/src/backend/internal/mod.rs @@ -9,7 +9,7 @@ pub mod manage; use crate::Type; use ahash::AHashMap; -use compact_str::CompactString; + use std::fmt::Display; use store::{Deserialize, SerializeInfallible, U32_LEN, write::key::KeySerializer}; use utils::codec::leb128::Leb128Iterator; @@ -140,8 +140,8 @@ pub enum PrincipalAction { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)] #[serde(untagged)] pub enum PrincipalValue { - String(CompactString), - StringList(Vec), + String(String), + StringList(Vec), Integer(u64), IntegerList(Vec), } diff --git a/crates/directory/src/backend/ldap/lookup.rs b/crates/directory/src/backend/ldap/lookup.rs index f6edebf3..d222a72e 100644 --- a/crates/directory/src/backend/ldap/lookup.rs +++ b/crates/directory/src/backend/ldap/lookup.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; use ldap3::{Ldap, LdapConnAsync, ResultEntry, Scope, SearchEntry}; use mail_send::Credentials; use store::xxhash_rust; @@ -298,11 +297,11 @@ impl LdapDirectory { } } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { self.data_store.vrfy(address).await } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { self.data_store.expn(address).await } @@ -351,44 +350,39 @@ impl LdapMappings { for (attr, value) in entry.attrs { if self.attr_name.contains(&attr) { if !self.attr_email_address.contains(&attr) { - principal.name = value.into_iter().next().unwrap_or_default().into(); + principal.name = value.into_iter().next().unwrap_or_default(); } else { for (idx, item) in value.into_iter().enumerate() { - principal - .emails - .insert(0, CompactString::from_str_to_lowercase(&item)); + principal.emails.insert(0, item.to_lowercase()); if idx == 0 { - principal.name = item.into(); + principal.name = item; } } } } else if self.attr_secret.contains(&attr) { for item in value { - principal.secrets.push(item.into()); + principal.secrets.push(item); } } else if self.attr_secret_changed.contains(&attr) { // Create a disabled AppPassword, used to indicate that the password has been changed // but cannot be used for authentication. for item in value { - principal.secrets.push( - format!("$app${}$", xxhash_rust::xxh3::xxh3_64(item.as_bytes())).into(), - ); + principal.secrets.push(format!( + "$app${}$", + xxhash_rust::xxh3::xxh3_64(item.as_bytes()) + )); } } else if self.attr_email_address.contains(&attr) { for item in value { - principal - .emails - .insert(0, CompactString::from_str_to_lowercase(&item)); + principal.emails.insert(0, item.to_lowercase()); } } else if self.attr_email_alias.contains(&attr) { for item in value { - principal - .emails - .push(CompactString::from_str_to_lowercase(&item)); + principal.emails.push(item.to_lowercase()); } } else if let Some(idx) = self.attr_description.iter().position(|a| a == &attr) { if principal.description.is_none() || idx == 0 { - principal.description = value.into_iter().next().map(Into::into); + principal.description = value.into_iter().next(); } } else if self.attr_groups.contains(&attr) { member_of.extend(value); diff --git a/crates/directory/src/backend/memory/config.rs b/crates/directory/src/backend/memory/config.rs index eda5c484..a6aac415 100644 --- a/crates/directory/src/backend/memory/config.rs +++ b/crates/directory/src/backend/memory/config.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use store::Store; use utils::config::{Config, utils::AsKey}; @@ -119,7 +119,7 @@ impl MemoryDirectory { principal .emails - .push(CompactString::from_str_to_lowercase(email)); + .push(email.to_lowercase()); } // Parse mailing lists diff --git a/crates/directory/src/backend/memory/lookup.rs b/crates/directory/src/backend/memory/lookup.rs index 41a3221e..ff88167e 100644 --- a/crates/directory/src/backend/memory/lookup.rs +++ b/crates/directory/src/backend/memory/lookup.rs @@ -6,7 +6,7 @@ use super::{EmailType, MemoryDirectory}; use crate::{Principal, QueryBy, backend::RcptType}; -use compact_str::CompactString; + use mail_send::Credentials; impl MemoryDirectory { @@ -62,7 +62,7 @@ impl MemoryDirectory { Ok(self.emails_to_ids.contains_key(address).into()) } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { let mut result = Vec::new(); for (key, value) in &self.emails_to_ids { if key.contains(address) && value.iter().any(|t| matches!(t, EmailType::Primary(_))) { @@ -72,7 +72,7 @@ impl MemoryDirectory { Ok(result) } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { let mut result = Vec::new(); for (key, value) in &self.emails_to_ids { if key == address { diff --git a/crates/directory/src/backend/mod.rs b/crates/directory/src/backend/mod.rs index 6f5d7573..939a5148 100644 --- a/crates/directory/src/backend/mod.rs +++ b/crates/directory/src/backend/mod.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + pub mod imap; pub mod internal; @@ -17,7 +17,7 @@ pub mod sql; #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] pub enum RcptType { Mailbox, - List(Vec), + List(Vec), #[default] Invalid, } diff --git a/crates/directory/src/backend/oidc/lookup.rs b/crates/directory/src/backend/oidc/lookup.rs index 6b7f5383..75506411 100644 --- a/crates/directory/src/backend/oidc/lookup.rs +++ b/crates/directory/src/backend/oidc/lookup.rs @@ -5,7 +5,7 @@ */ use ahash::HashMap; -use compact_str::CompactString; + use mail_send::Credentials; use reqwest::{StatusCode, header::AUTHORIZATION}; use trc::{AddContext, AuthEvent}; @@ -145,11 +145,11 @@ impl OpenIdDirectory { self.data_store.rcpt(address).await } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { self.data_store.vrfy(address).await } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { self.data_store.expn(address).await } @@ -188,10 +188,10 @@ impl BuildPrincipal for OpenIdResponse { Ok(Principal { id: u32::MAX, typ: Type::Individual, - name: username.into(), - description: full_name.map(Into::into), + name: username, + description: full_name, secrets: Default::default(), - emails: vec![email.into()], + emails: vec![email], quota: Default::default(), tenant: Default::default(), data: vec![PrincipalData::Roles(vec![ROLE_USER])], diff --git a/crates/directory/src/backend/smtp/lookup.rs b/crates/directory/src/backend/smtp/lookup.rs index f57aac0b..d4fbd7b4 100644 --- a/crates/directory/src/backend/smtp/lookup.rs +++ b/crates/directory/src/backend/smtp/lookup.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use mail_send::{Credentials, smtp::AssertReply}; use smtp_proto::Severity; @@ -67,7 +67,7 @@ impl SmtpDirectory { } } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { self.pool .get() .await @@ -76,7 +76,7 @@ impl SmtpDirectory { .await } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { self.pool .get() .await @@ -111,7 +111,7 @@ impl SmtpClient { } } - async fn expand(&mut self, command: &str) -> trc::Result> { + async fn expand(&mut self, command: &str) -> trc::Result> { let reply = self .client .cmd(command.as_bytes()) @@ -122,7 +122,7 @@ impl SmtpClient { .message() .split('\n') .map(|p| p.into()) - .collect::>()), + .collect::>()), code @ (550 | 551 | 553 | 500 | 502) => { Err(trc::StoreEvent::NotSupported.ctx(trc::Key::Code, code)) } diff --git a/crates/directory/src/backend/sql/lookup.rs b/crates/directory/src/backend/sql/lookup.rs index 9a4ba238..24ebd7bf 100644 --- a/crates/directory/src/backend/sql/lookup.rs +++ b/crates/directory/src/backend/sql/lookup.rs @@ -15,7 +15,7 @@ use crate::{ }, }, }; -use compact_str::CompactString; + use mail_send::Credentials; use store::{NamedRows, Rows, Value}; use trc::AddContext; @@ -250,11 +250,11 @@ impl SqlDirectory { } } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { self.data_store.vrfy(address).await } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { self.data_store.expn(address).await } @@ -298,7 +298,7 @@ impl SqlMappings { if let Value::Text(text) = value { principal .emails - .push(CompactString::from_str_to_lowercase(text.as_ref())); + .push(text.to_lowercase()); } } else if name.eq_ignore_ascii_case(&self.column_quota) { if let Value::Integer(quota) = value { diff --git a/crates/directory/src/core/dispatch.rs b/crates/directory/src/core/dispatch.rs index f38fce5a..5343726e 100644 --- a/crates/directory/src/core/dispatch.rs +++ b/crates/directory/src/core/dispatch.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use trc::AddContext; use crate::{ @@ -97,7 +97,7 @@ impl Directory { Ok(result) } - pub async fn vrfy(&self, address: &str) -> trc::Result> { + pub async fn vrfy(&self, address: &str) -> trc::Result> { match &self.store { DirectoryInner::Internal(store) => store.vrfy(address).await, DirectoryInner::Ldap(store) => store.vrfy(address).await, @@ -110,7 +110,7 @@ impl Directory { .caused_by(trc::location!()) } - pub async fn expn(&self, address: &str) -> trc::Result> { + pub async fn expn(&self, address: &str) -> trc::Result> { match &self.store { DirectoryInner::Internal(store) => store.expn(address).await, DirectoryInner::Ldap(store) => store.expn(address).await, diff --git a/crates/directory/src/core/principal.rs b/crates/directory/src/core/principal.rs index 778f945b..28645e1d 100644 --- a/crates/directory/src/core/principal.rs +++ b/crates/directory/src/core/principal.rs @@ -6,7 +6,6 @@ use std::{collections::hash_map::Entry, fmt, str::FromStr}; -use compact_str::CompactString; use serde::{ Deserializer, Serializer, de::{self, IgnoredAny, Visitor}, @@ -76,7 +75,7 @@ impl Principal { // SPDX-SnippetEnd pub fn description(&self) -> Option<&str> { - self.description.as_ref().map(|d| d.as_str()) + self.description.as_deref() } pub fn member_of(&self) -> &[u32] { @@ -128,7 +127,7 @@ impl Principal { .unwrap_or_default() } - pub fn urls(&self) -> &[CompactString] { + pub fn urls(&self) -> &[String] { self.data .iter() .find_map(|item| { @@ -164,7 +163,7 @@ impl Principal { .unwrap_or_default() } - pub fn picture(&self) -> Option<&CompactString> { + pub fn picture(&self) -> Option<&String> { self.data.iter().find_map(|item| { if let PrincipalData::Picture(picture) = item { picture.into() @@ -174,7 +173,7 @@ impl Principal { }) } - pub fn picture_mut(&mut self) -> Option<&mut CompactString> { + pub fn picture_mut(&mut self) -> Option<&mut String> { self.data.iter_mut().find_map(|item| { if let PrincipalData::Picture(picture) = item { picture.into() @@ -299,7 +298,7 @@ impl Principal { updates } - pub fn fallback_admin(fallback_pass: impl Into) -> Self { + pub fn fallback_admin(fallback_pass: impl Into) -> Self { Principal { id: u32::MAX, typ: Type::Individual, @@ -363,7 +362,7 @@ impl PrincipalSet { self.fields.get(&key).and_then(|v| v.as_int()) } - pub fn get_str_array(&self, key: PrincipalField) -> Option<&[CompactString]> { + pub fn get_str_array(&self, key: PrincipalField) -> Option<&[String]> { self.fields.get(&key).and_then(|v| match v { PrincipalValue::StringList(v) => Some(v.as_slice()), PrincipalValue::String(v) => Some(std::slice::from_ref(v)), @@ -383,12 +382,12 @@ impl PrincipalSet { self.fields.remove(&key) } - pub fn take_str(&mut self, key: PrincipalField) -> Option { + pub fn take_str(&mut self, key: PrincipalField) -> Option { self.take(key).and_then(|v| match v { PrincipalValue::String(s) => Some(s), PrincipalValue::StringList(l) => l.into_iter().next(), - PrincipalValue::Integer(i) => Some(i.to_string().into()), - PrincipalValue::IntegerList(l) => l.into_iter().next().map(|i| i.to_string().into()), + PrincipalValue::Integer(i) => Some(i.to_string()), + PrincipalValue::IntegerList(l) => l.into_iter().next().map(|i| i.to_string()), }) } @@ -401,7 +400,7 @@ impl PrincipalSet { }) } - pub fn take_str_array(&mut self, key: PrincipalField) -> Option> { + pub fn take_str_array(&mut self, key: PrincipalField) -> Option> { self.take(key).map(|v| v.into_str_array()) } @@ -412,7 +411,7 @@ impl PrincipalSet { pub fn iter_str( &self, key: PrincipalField, - ) -> Box + Sync + Send + '_> { + ) -> Box + Sync + Send + '_> { self.fields .get(&key) .map(|v| v.iter_str()) @@ -422,7 +421,7 @@ impl PrincipalSet { pub fn iter_mut_str( &mut self, key: PrincipalField, - ) -> Box + Sync + Send + '_> { + ) -> Box + Sync + Send + '_> { self.fields .get_mut(&key) .map(|v| v.iter_mut_str()) @@ -488,11 +487,7 @@ impl PrincipalSet { self } - pub fn append_str( - &mut self, - key: PrincipalField, - value: impl Into, - ) -> &mut Self { + pub fn append_str(&mut self, key: PrincipalField, value: impl Into) -> &mut Self { let value = value.into(); match self.fields.entry(key) { Entry::Occupied(v) => { @@ -510,12 +505,12 @@ impl PrincipalSet { } } PrincipalValue::Integer(i) => { - *v = PrincipalValue::StringList(vec![i.to_string().into(), value]); + *v = PrincipalValue::StringList(vec![i.to_string(), value]); } PrincipalValue::IntegerList(l) => { *v = PrincipalValue::StringList( l.iter() - .map(|i| i.to_string().into()) + .map(|i| i.to_string()) .chain(std::iter::once(value)) .collect(), ); @@ -529,11 +524,7 @@ impl PrincipalSet { self } - pub fn prepend_str( - &mut self, - key: PrincipalField, - value: impl Into, - ) -> &mut Self { + pub fn prepend_str(&mut self, key: PrincipalField, value: impl Into) -> &mut Self { let value = value.into(); match self.fields.entry(key) { Entry::Occupied(v) => { @@ -551,12 +542,12 @@ impl PrincipalSet { } } PrincipalValue::Integer(i) => { - *v = PrincipalValue::StringList(vec![value, i.to_string().into()]); + *v = PrincipalValue::StringList(vec![value, i.to_string()]); } PrincipalValue::IntegerList(l) => { *v = PrincipalValue::StringList( std::iter::once(value) - .chain(l.iter().map(|i| i.to_string().into())) + .chain(l.iter().map(|i| i.to_string())) .collect(), ); } @@ -629,7 +620,7 @@ impl PrincipalSet { pub fn retain_str(&mut self, key: PrincipalField, mut f: F) where - F: FnMut(&CompactString) -> bool, + F: FnMut(&String) -> bool, { if let Some(value) = self.fields.get_mut(&key) { match value { @@ -689,7 +680,7 @@ impl PrincipalValue { } } - pub fn iter_str(&self) -> Box + Sync + Send + '_> { + pub fn iter_str(&self) -> Box + Sync + Send + '_> { match self { PrincipalValue::String(v) => Box::new(std::iter::once(v)), PrincipalValue::StringList(v) => Box::new(v.iter()), @@ -697,9 +688,7 @@ impl PrincipalValue { } } - pub fn iter_mut_str( - &mut self, - ) -> Box + Sync + Send + '_> { + pub fn iter_mut_str(&mut self) -> Box + Sync + Send + '_> { match self { PrincipalValue::String(v) => Box::new(std::iter::once(v)), PrincipalValue::StringList(v) => Box::new(v.iter_mut()), @@ -731,12 +720,12 @@ impl PrincipalValue { } } - pub fn into_str_array(self) -> Vec { + pub fn into_str_array(self) -> Vec { match self { PrincipalValue::StringList(v) => v, PrincipalValue::String(v) => vec![v], - PrincipalValue::Integer(v) => vec![v.to_string().into()], - PrincipalValue::IntegerList(v) => v.into_iter().map(|v| v.to_string().into()).collect(), + PrincipalValue::Integer(v) => vec![v.to_string()], + PrincipalValue::IntegerList(v) => v.into_iter().map(|v| v.to_string()).collect(), } } @@ -776,8 +765,8 @@ impl From for PrincipalValue { } } -impl From for PrincipalValue { - fn from(v: CompactString) -> Self { +impl From for PrincipalValue { + fn from(v: String) -> Self { Self::String(v) } } @@ -788,8 +777,8 @@ impl From<&str> for PrincipalValue { } } -impl From> for PrincipalValue { - fn from(v: Vec) -> Self { +impl From> for PrincipalValue { + fn from(v: Vec) -> Self { Self::StringList(v) } } @@ -956,7 +945,7 @@ impl<'de> serde::Deserialize<'de> for PrincipalValue { E: de::Error, { if value.len() <= MAX_STRING_LEN { - Ok(PrincipalValue::String(value.into())) + Ok(PrincipalValue::String(value)) } else { Err(serde::de::Error::custom("string too long")) } @@ -984,7 +973,7 @@ impl<'de> serde::Deserialize<'de> for PrincipalValue { match value { StringOrU64::String(s) => { if s.len() <= MAX_STRING_LEN { - vec_string.push(s.into()); + vec_string.push(s); } else { return Err(serde::de::Error::custom("string too long")); } @@ -1042,19 +1031,19 @@ impl<'de> serde::Deserialize<'de> for PrincipalSet { })?; let value = match key { - PrincipalField::Name => PrincipalValue::String( - map.next_value::().and_then(|v| { + PrincipalField::Name => { + PrincipalValue::String(map.next_value::().and_then(|v| { if v.len() <= MAX_STRING_LEN { Ok(v) } else { Err(serde::de::Error::custom("string too long")) } - })?, - ), + })?) + } PrincipalField::Description | PrincipalField::Tenant | PrincipalField::Picture => { - if let Some(v) = map.next_value::>()? { + if let Some(v) = map.next_value::>()? { if v.len() <= MAX_STRING_LEN { PrincipalValue::String(v) } else { @@ -1166,8 +1155,8 @@ impl<'de> serde::Deserialize<'de> for StringOrU64 { #[derive(Debug)] enum StringOrMany { - One(CompactString), - Many(Vec), + One(String), + Many(Vec), } impl<'de> serde::Deserialize<'de> for StringOrMany { @@ -1200,7 +1189,7 @@ impl<'de> serde::Deserialize<'de> for StringOrMany { E: de::Error, { if v.len() <= MAX_STRING_LEN { - Ok(StringOrMany::One(v.into())) + Ok(StringOrMany::One(v)) } else { Err(serde::de::Error::custom("string too long")) } @@ -1212,7 +1201,7 @@ impl<'de> serde::Deserialize<'de> for StringOrMany { { let mut vec = Vec::new(); - while let Some(value) = seq.next_element::()? { + while let Some(value) = seq.next_element::()? { vec.push(value); } diff --git a/crates/directory/src/core/secret.rs b/crates/directory/src/core/secret.rs index e17e25d1..7b425fc7 100644 --- a/crates/directory/src/core/secret.rs +++ b/crates/directory/src/core/secret.rs @@ -5,6 +5,7 @@ */ use argon2::Argon2; +use compact_str::ToCompactString; use mail_builder::encoders::base64::base64_encode; use mail_parser::decoders::base64::base64_decode; use password_hash::PasswordHash; @@ -57,7 +58,7 @@ impl Principal { .map_err(|err| { trc::AuthEvent::Error .reason(err) - .details(secret.to_string()) + .details(secret.to_compact_string()) })? .check_current(totp_token) .unwrap_or(false); diff --git a/crates/directory/src/lib.rs b/crates/directory/src/lib.rs index 6d832400..35a3cfcc 100644 --- a/crates/directory/src/lib.rs +++ b/crates/directory/src/lib.rs @@ -17,7 +17,7 @@ use backend::{ smtp::SmtpDirectory, sql::SqlDirectory, }; -use compact_str::CompactString; + use deadpool::managed::PoolError; use ldap3::LdapError; use mail_send::Credentials; @@ -37,10 +37,10 @@ pub struct Directory { pub struct Principal { pub id: u32, pub typ: Type, - pub name: CompactString, - pub description: Option, - pub secrets: Vec, - pub emails: Vec, + pub name: String, + pub description: Option, + pub secrets: Vec, + pub emails: Vec, pub quota: Option, pub tenant: Option, pub data: Vec, @@ -58,9 +58,9 @@ pub enum PrincipalData { Roles(Vec), Lists(Vec), Permissions(Vec), - Picture(CompactString), - ExternalMembers(Vec), - Urls(Vec), + Picture(String), + ExternalMembers(Vec), + Urls(Vec), PrincipalQuota(Vec), } diff --git a/crates/email/src/identity/mod.rs b/crates/email/src/identity/mod.rs index 9a7e73f7..00843e89 100644 --- a/crates/email/src/identity/mod.rs +++ b/crates/email/src/identity/mod.rs @@ -6,25 +6,25 @@ pub mod index; -use compact_str::CompactString; + use store::{SERIALIZE_IDENTITY_V1, SerializedVersion}; #[derive( rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq, )] pub struct Identity { - pub name: CompactString, - pub email: CompactString, + pub name: String, + pub email: String, pub reply_to: Option>, pub bcc: Option>, - pub text_signature: CompactString, - pub html_signature: CompactString, + pub text_signature: String, + pub html_signature: String, } #[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Clone, PartialEq, Eq)] pub struct EmailAddress { - pub name: Option, - pub email: CompactString, + pub name: Option, + pub email: String, } impl SerializedVersion for Identity { diff --git a/crates/email/src/mailbox/cache.rs b/crates/email/src/mailbox/cache.rs index 60d30038..619e5af2 100644 --- a/crates/email/src/mailbox/cache.rs +++ b/crates/email/src/mailbox/cache.rs @@ -10,7 +10,7 @@ use common::{ CacheSwap, MailboxCache, MailboxStoreCache, Server, auth::AccessToken, config::jmap::settings::SpecialUse, sharing::EffectiveAcl, }; -use compact_str::CompactString; + use jmap_proto::types::{acl::Acl, collection::Collection, value::AclGrant}; use std::future::Future; use store::{ @@ -242,7 +242,7 @@ fn build_tree(cache: &mut MailboxStoreCache) { mailbox.path = if matches!(mailbox.role, SpecialUse::Inbox) { "INBOX".into() } else if mailbox.is_root() && mailbox.name.as_str().eq_ignore_ascii_case("inbox") { - format!("INBOX {}", idx + 1).into() + format!("INBOX {}", idx + 1) } else { mailbox.name.clone() }; @@ -264,7 +264,7 @@ fn build_tree(cache: &mut MailboxStoreCache) { cache.by_id(&parent_id).map(|folder| (path, &folder.path)) }) { - let mut new_path = CompactString::with_capacity(parent_path.len() + path.len() + 1); + let mut new_path = String::with_capacity(parent_path.len() + path.len() + 1); new_path.push_str(parent_path.as_str()); new_path.push('/'); new_path.push_str(path.as_str()); diff --git a/crates/email/src/mailbox/mod.rs b/crates/email/src/mailbox/mod.rs index 3def19ef..8f09b0bc 100644 --- a/crates/email/src/mailbox/mod.rs +++ b/crates/email/src/mailbox/mod.rs @@ -5,7 +5,7 @@ */ use common::config::jmap::settings::SpecialUse; -use compact_str::CompactString; + use jmap_proto::types::value::AclGrant; use store::{SERIALIZE_MAILBOX_V1, SerializedVersion}; @@ -25,7 +25,7 @@ pub const TOMBSTONE_ID: u32 = u32::MAX - 1; #[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Clone, PartialEq, Eq)] #[rkyv(derive(Debug))] pub struct Mailbox { - pub name: CompactString, + pub name: String, pub role: SpecialUse, pub parent_id: u32, pub sort_order: Option, @@ -48,7 +48,7 @@ impl SerializedVersion for Mailbox { } impl Mailbox { - pub fn new(name: impl Into) -> Self { + pub fn new(name: impl Into) -> Self { Mailbox { name: name.into(), role: SpecialUse::None, diff --git a/crates/email/src/message/cache.rs b/crates/email/src/message/cache.rs index 0ba1a5ee..114d5495 100644 --- a/crates/email/src/message/cache.rs +++ b/crates/email/src/message/cache.rs @@ -9,7 +9,7 @@ use common::{ CacheSwap, MailboxStoreCache, MessageCache, MessageStoreCache, MessageUidCache, Server, auth::AccessToken, sharing::EffectiveAcl, }; -use compact_str::CompactString; + use jmap_proto::types::{ acl::Acl, collection::Collection, @@ -227,7 +227,7 @@ fn insert_item(cache: &mut MessageStoreCache, document_id: u32, message: &Archiv if let Some(idx) = cache.keywords.iter().position(|k| k == custom) { item.keywords |= 1 << (OTHER + idx); } else if cache.keywords.len() < (128 - OTHER) { - cache.keywords.push(CompactString::from(custom)); + cache.keywords.push(String::from(custom)); item.keywords |= 1 << (OTHER + cache.keywords.len() - 1); } } diff --git a/crates/email/src/message/delivery.rs b/crates/email/src/message/delivery.rs index 5be00bd9..9e2b3c5e 100644 --- a/crates/email/src/message/delivery.rs +++ b/crates/email/src/message/delivery.rs @@ -5,7 +5,7 @@ */ use common::Server; -use compact_str::CompactString; + use directory::Permission; use jmap_proto::types::{state::StateChange, type_state::DataType}; use mail_parser::MessageParser; @@ -19,8 +19,8 @@ use super::ingest::{EmailIngest, IngestEmail, IngestSource}; #[derive(Debug)] pub struct IngestMessage { - pub sender_address: CompactString, - pub recipients: Vec, + pub sender_address: String, + pub recipients: Vec, pub message_blob: BlobHash, pub message_size: u64, pub session_id: u64, @@ -44,8 +44,8 @@ pub struct LocalDeliveryResult { } pub struct AutogeneratedMessage { - pub sender_address: CompactString, - pub recipients: Vec, + pub sender_address: String, + pub recipients: Vec, pub message: Vec, } diff --git a/crates/email/src/push/mod.rs b/crates/email/src/push/mod.rs index 09421759..1f2a4ee5 100644 --- a/crates/email/src/push/mod.rs +++ b/crates/email/src/push/mod.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; use jmap_proto::types::type_state::DataType; use store::{SERIALIZE_PUSH_V1, SerializedVersion}; use utils::map::bitmap::Bitmap; @@ -13,10 +12,10 @@ use utils::map::bitmap::Bitmap; rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Default, Debug, Clone, PartialEq, Eq, )] pub struct PushSubscription { - pub url: CompactString, - pub device_client_id: CompactString, + pub url: String, + pub device_client_id: String, pub expires: u64, - pub verification_code: CompactString, + pub verification_code: String, pub verified: bool, pub types: Bitmap, pub keys: Option, diff --git a/crates/email/src/sieve/ingest.rs b/crates/email/src/sieve/ingest.rs index 92b0fa16..98d0ae9f 100644 --- a/crates/email/src/sieve/ingest.rs +++ b/crates/email/src/sieve/ingest.rs @@ -20,7 +20,7 @@ use crate::{ use common::{ Server, auth::AccessToken, config::jmap::settings::SpecialUse, scripts::plugins::PluginContext, }; -use compact_str::CompactString; + use directory::{Permission, QueryBy}; use jmap_proto::types::{collection::Collection, id::Id, keyword::Keyword, property::Property}; use mail_parser::MessageParser; @@ -377,11 +377,9 @@ impl SieveScriptIngest for Server { } => { input = true.into(); if let Some(message) = messages.get(message_id) { - let recipients: Vec = match recipient { - Recipient::Address(rcpt) => vec![rcpt.into()], - Recipient::Group(rcpts) => { - rcpts.into_iter().map(CompactString::from).collect() - } + let recipients: Vec = match recipient { + Recipient::Address(rcpt) => vec![rcpt], + Recipient::Group(rcpts) => rcpts, Recipient::List(_) => { // Not yet implemented continue; @@ -394,7 +392,7 @@ impl SieveScriptIngest for Server { From = mail_from.clone(), To = recipients .iter() - .map(|r| trc::Value::String(r.clone())) + .map(|r| trc::Value::String(r.as_str().into())) .collect::>(), Size = message.raw_message.len(), SpanId = session_id @@ -411,7 +409,7 @@ impl SieveScriptIngest for Server { From = mail_from.clone(), To = recipients .iter() - .map(|r| trc::Value::String(r.clone())) + .map(|r| trc::Value::String(r.as_str().into())) .collect::>(), Size = message.raw_message.len(), Limit = self.core.jmap.mail_max_size, @@ -722,6 +720,6 @@ impl SieveScriptIngest for Server { pub struct CompiledScript { pub script: Sieve, - pub name: CompactString, + pub name: String, pub hash: u32, } diff --git a/crates/email/src/sieve/mod.rs b/crates/email/src/sieve/mod.rs index 29f673d8..679485e5 100644 --- a/crates/email/src/sieve/mod.rs +++ b/crates/email/src/sieve/mod.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use common::KV_SIEVE_ID; -use compact_str::CompactString; + use sieve::Sieve; use store::{SERIALIZE_SIEVE_V1, SerializedVersion, blake3}; use utils::BlobHash; @@ -21,7 +21,7 @@ pub mod ingest; pub struct ActiveScript { pub document_id: u32, pub hash: u32, - pub script_name: CompactString, + pub script_name: String, pub script: Arc, } @@ -30,7 +30,7 @@ pub struct ActiveScript { )] #[rkyv(derive(Debug))] pub struct SieveScript { - pub name: CompactString, + pub name: String, pub is_active: bool, pub blob_hash: BlobHash, pub size: u32, @@ -50,13 +50,13 @@ impl SerializedVersion for SieveScript { pub struct VacationResponse { pub from_date: Option, pub to_date: Option, - pub subject: Option, - pub text_body: Option, - pub html_body: Option, + pub subject: Option, + pub text_body: Option, + pub html_body: Option, } impl SieveScript { - pub fn new(name: impl Into, blob_hash: BlobHash) -> Self { + pub fn new(name: impl Into, blob_hash: BlobHash) -> Self { SieveScript { name: name.into(), is_active: false, @@ -66,7 +66,7 @@ impl SieveScript { } } - pub fn with_name(mut self, name: impl Into) -> Self { + pub fn with_name(mut self, name: impl Into) -> Self { self.name = name.into(); self } diff --git a/crates/groupware/src/calendar/mod.rs b/crates/groupware/src/calendar/mod.rs index f2c7b800..68ada96a 100644 --- a/crates/groupware/src/calendar/mod.rs +++ b/crates/groupware/src/calendar/mod.rs @@ -7,7 +7,7 @@ use std::collections::HashMap; use calcard::icalendar::ICalendar; -use compact_str::CompactString; + use dav_proto::schema::request::DeadProperty; use jmap_proto::types::{acl::Acl, value::AclGrant}; use store::{SERIALIZE_CALENDAR_V1, SERIALIZE_CALENDAREVENT_V1, SerializedVersion, ahash}; @@ -19,7 +19,7 @@ use crate::DavName; rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq, )] pub struct Calendar { - pub name: CompactString, + pub name: String, pub preferences: HashMap, pub acls: Vec, pub dead_properties: DeadProperty, @@ -31,16 +31,16 @@ pub struct Calendar { rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq, )] pub struct CalendarPreferences { - pub name: CompactString, - pub description: Option, + pub name: String, + pub description: Option, pub sort_order: u32, - pub color: Option, + pub color: Option, pub is_subscribed: bool, pub is_default: bool, pub is_visible: bool, pub include_in_availability: IncludeInAvailability, - pub default_alerts_with_time: HashMap, - pub default_alerts_without_time: HashMap, + pub default_alerts_with_time: HashMap, + pub default_alerts_without_time: HashMap, pub time_zone: Timezone, } @@ -49,7 +49,7 @@ pub struct CalendarPreferences { )] pub struct CalendarEvent { pub names: Vec, - pub display_name: Option, + pub display_name: Option, pub event: ICalendar, pub user_properties: VecMap, pub may_invite_self: bool, @@ -66,7 +66,7 @@ pub struct CalendarEvent { rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq, )] pub enum Timezone { - IANA(CompactString), + IANA(String), Custom(ICalendar), #[default] Default, diff --git a/crates/groupware/src/contact/mod.rs b/crates/groupware/src/contact/mod.rs index 96a65a99..5404f6d0 100644 --- a/crates/groupware/src/contact/mod.rs +++ b/crates/groupware/src/contact/mod.rs @@ -7,6 +7,7 @@ pub mod index; use calcard::vcard::VCard; + use dav_proto::schema::request::DeadProperty; use jmap_proto::types::{acl::Acl, value::AclGrant}; use store::{SERIALIZE_ADDRESSBOOK_V1, SERIALIZE_CALENDAREVENT_V1, SerializedVersion}; diff --git a/crates/groupware/src/file/mod.rs b/crates/groupware/src/file/mod.rs index ff21a5da..d7e3b843 100644 --- a/crates/groupware/src/file/mod.rs +++ b/crates/groupware/src/file/mod.rs @@ -6,6 +6,7 @@ pub mod index; + use dav_proto::schema::request::DeadProperty; use jmap_proto::types::value::AclGrant; use store::{SERIALIZE_FILENODE_V1, SerializedVersion}; diff --git a/crates/groupware/src/lib.rs b/crates/groupware/src/lib.rs index e671afde..ec41564f 100644 --- a/crates/groupware/src/lib.rs +++ b/crates/groupware/src/lib.rs @@ -64,7 +64,7 @@ impl Deserialize for DavName { .caused_by(trc::location!()) .ctx(trc::Key::Value, bytes) })? - .to_string(); + .into(); Ok(DavName { name, parent_id }) } diff --git a/crates/http-proto/src/context.rs b/crates/http-proto/src/context.rs index c04cfa5d..54ade8de 100644 --- a/crates/http-proto/src/context.rs +++ b/crates/http-proto/src/context.rs @@ -8,7 +8,7 @@ use common::{ Server, expr::{functions::ResolveVariable, *}, }; -use compact_str::{CompactString, ToCompactString, format_compact}; +use compact_str::{ToCompactString, format_compact}; use hyper::StatusCode; use crate::{HttpContext, HttpRequest, HttpSessionData}; @@ -18,7 +18,7 @@ impl<'x> HttpContext<'x> { Self { session, req } } - pub async fn resolve_response_url(&self, server: &Server) -> CompactString { + pub async fn resolve_response_url(&self, server: &Server) -> String { server .eval_if( &server.core.network.http_response_url, @@ -27,7 +27,7 @@ impl<'x> HttpContext<'x> { ) .await .unwrap_or_else(|| { - format_compact!( + format!( "http{}://{}:{}", if self.session.is_tls { "s" } else { "" }, self.session.local_ip, @@ -67,12 +67,8 @@ impl ResolveVariable for HttpContext<'_> { .iter() .map(|(h, v)| { Variable::String( - CompactString::new(format_compact!( - "{}: {}", - h.as_str(), - v.to_str().unwrap_or_default() - )) - .into(), + format_compact!("{}: {}", h.as_str(), v.to_str().unwrap_or_default()) + .into(), ) }) .collect::>() diff --git a/crates/http/src/auth/oauth/openid.rs b/crates/http/src/auth/oauth/openid.rs index beab2c1e..a21f7cad 100644 --- a/crates/http/src/auth/oauth/openid.rs +++ b/crates/http/src/auth/oauth/openid.rs @@ -10,25 +10,24 @@ use common::{ Server, auth::{AccessToken, oauth::oidc::Userinfo}, }; -use compact_str::{CompactString, ToCompactString, format_compact}; use serde::{Deserialize, Serialize}; use http_proto::*; #[derive(Debug, Serialize, Deserialize)] pub struct OpenIdMetadata { - pub issuer: CompactString, - pub authorization_endpoint: CompactString, - pub token_endpoint: CompactString, - pub userinfo_endpoint: CompactString, - pub jwks_uri: CompactString, - pub registration_endpoint: CompactString, - pub scopes_supported: Vec, - pub response_types_supported: Vec, - pub subject_types_supported: Vec, - pub grant_types_supported: Vec, - pub id_token_signing_alg_values_supported: Vec, - pub claims_supported: Vec, + pub issuer: String, + pub authorization_endpoint: String, + pub token_endpoint: String, + pub userinfo_endpoint: String, + pub jwks_uri: String, + pub registration_endpoint: String, + pub scopes_supported: Vec, + pub response_types_supported: Vec, + pub subject_types_supported: Vec, + pub grant_types_supported: Vec, + pub id_token_signing_alg_values_supported: Vec, + pub claims_supported: Vec, } pub trait OpenIdHandler: Sync + Send { @@ -50,7 +49,7 @@ impl OpenIdHandler for Server { access_token: &AccessToken, ) -> trc::Result { Ok(JsonResponse::new(Userinfo { - sub: Some(access_token.primary_id.to_compact_string()), + sub: Some(access_token.primary_id.to_string()), name: access_token.description.clone(), preferred_username: Some(access_token.name.clone()), email: access_token.emails.first().cloned(), @@ -71,11 +70,11 @@ impl OpenIdHandler for Server { .await; Ok(JsonResponse::new(OpenIdMetadata { - authorization_endpoint: format_compact!("{base_url}/authorize/code",), - token_endpoint: format_compact!("{base_url}/auth/token"), - userinfo_endpoint: format_compact!("{base_url}/auth/userinfo"), - jwks_uri: format_compact!("{base_url}/auth/jwks.json"), - registration_endpoint: format_compact!("{base_url}/auth/register"), + authorization_endpoint: format!("{base_url}/authorize/code",), + token_endpoint: format!("{base_url}/auth/token"), + userinfo_endpoint: format!("{base_url}/auth/userinfo"), + jwks_uri: format!("{base_url}/auth/jwks.json"), + registration_endpoint: format!("{base_url}/auth/register"), response_types_supported: vec![ "code".into(), "id_token".into(), diff --git a/crates/http/src/auth/oauth/registration.rs b/crates/http/src/auth/oauth/registration.rs index 4c9e1418..458f06b9 100644 --- a/crates/http/src/auth/oauth/registration.rs +++ b/crates/http/src/auth/oauth/registration.rs @@ -10,7 +10,7 @@ use common::{ Server, auth::oauth::registration::{ClientRegistrationRequest, ClientRegistrationResponse}, }; -use compact_str::CompactString; + use directory::{ Permission, QueryBy, Type, backend::internal::{ @@ -70,7 +70,7 @@ impl ClientRegistrationHandler for Server { .sample_iter(Alphanumeric) .take(20) .map(|ch| char::from(ch.to_ascii_lowercase())) - .collect::(); + .collect::(); self.store() .create_principal( PrincipalSet::new(u32::MAX, Type::OauthClient) diff --git a/crates/http/src/auth/oauth/token.rs b/crates/http/src/auth/oauth/token.rs index b4ed3cfb..666cf828 100644 --- a/crates/http/src/auth/oauth/token.rs +++ b/crates/http/src/auth/oauth/token.rs @@ -11,7 +11,7 @@ use common::{ oauth::{GrantType, oidc::StandardClaims}, }, }; -use compact_str::CompactString; + use hyper::StatusCode; use std::future::Future; use store::{ @@ -45,8 +45,8 @@ pub trait TokenHandler: Sync + Send { &self, account_id: u32, client_id: &str, - issuer: CompactString, - nonce: Option, + issuer: String, + nonce: Option, with_refresh_token: bool, with_id_token: bool, ) -> impl Future> + Send; @@ -289,8 +289,8 @@ impl TokenHandler for Server { &self, account_id: u32, client_id: &str, - issuer: CompactString, - nonce: Option, + issuer: String, + nonce: Option, with_refresh_token: bool, with_id_token: bool, ) -> trc::Result { diff --git a/crates/http/src/autoconfig/mod.rs b/crates/http/src/autoconfig/mod.rs index a6a64e2c..6c54f54c 100644 --- a/crates/http/src/autoconfig/mod.rs +++ b/crates/http/src/autoconfig/mod.rs @@ -7,7 +7,7 @@ use std::fmt::Write; use common::{Server, manager::webadmin::Resource}; -use compact_str::CompactString; + use directory::QueryBy; use quick_xml::Reader; use quick_xml::events::Event; @@ -29,7 +29,7 @@ pub trait Autoconfig: Sync + Send { fn autoconfig_parameters<'x>( &self, emailaddress: &'x str, - ) -> impl Future> + Send; + ) -> impl Future> + Send; } impl Autoconfig for Server { @@ -177,7 +177,7 @@ impl Autoconfig for Server { async fn autoconfig_parameters<'x>( &self, emailaddress: &'x str, - ) -> trc::Result<(CompactString, CompactString, &'x str)> { + ) -> trc::Result<(String, String, &'x str)> { let (_, domain) = emailaddress.rsplit_once('@').ok_or_else(|| { trc::ResourceEvent::BadParameters .into_err() diff --git a/crates/http/src/form/mod.rs b/crates/http/src/form/mod.rs index 2830ab5f..e8489d69 100644 --- a/crates/http/src/form/mod.rs +++ b/crates/http/src/form/mod.rs @@ -12,7 +12,7 @@ use common::{ config::network::{ContactForm, FieldOrDefault}, ip_to_bytes, psl, }; -use compact_str::CompactString; + use email::message::delivery::{IngestMessage, LocalDeliveryStatus, MailDelivery}; use hyper::StatusCode; use mail_auth::common::cache::NoCache; @@ -86,8 +86,10 @@ impl FormHandler for Server { } // Obtain fields - let from_email = - CompactString::from_str_to_lowercase(form_data.get_or_default(&form.from_email).trim()); + let from_email = form_data + .get_or_default(&form.from_email) + .trim() + .to_lowercase(); let from_subject = form_data.get_or_default(&form.from_subject).trim(); let from_name = form_data.get_or_default(&form.from_name).trim(); diff --git a/crates/http/src/management/principal.rs b/crates/http/src/management/principal.rs index 383de1f6..2d47f30d 100644 --- a/crates/http/src/management/principal.rs +++ b/crates/http/src/management/principal.rs @@ -4,10 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::sync::Arc; - use common::{KV_BAYES_MODEL_USER, Server, auth::AccessToken}; -use compact_str::{CompactString, format_compact}; use directory::{ DirectoryInner, Permission, QueryBy, Type, backend::internal::{ @@ -19,35 +16,23 @@ use directory::{ }, }, }; - +use http_proto::{request::decode_path_element, *}; use hyper::{Method, header}; use serde_json::json; +use std::future::Future; +use std::sync::Arc; use trc::AddContext; use utils::url_params::UrlParams; -use http_proto::{request::decode_path_element, *}; -use std::future::Future; - #[derive(Debug, serde::Serialize, serde::Deserialize)] #[serde(tag = "type")] #[serde(rename_all = "camelCase")] pub enum AccountAuthRequest { - SetPassword { - password: CompactString, - }, - EnableOtpAuth { - url: CompactString, - }, - DisableOtpAuth { - url: Option, - }, - AddAppPassword { - name: CompactString, - password: CompactString, - }, - RemoveAppPassword { - name: Option, - }, + SetPassword { password: String }, + EnableOtpAuth { url: String }, + DisableOtpAuth { url: Option }, + AddAppPassword { name: String, password: String }, + RemoveAppPassword { name: Option }, } #[derive(Debug, serde::Serialize, serde::Deserialize)] @@ -55,7 +40,7 @@ pub struct AccountAuthResponse { #[serde(rename = "otpEnabled")] pub otp_auth: bool, #[serde(rename = "appPasswords")] - pub app_passwords: Vec, + pub app_passwords: Vec, } pub trait PrincipalManager: Sync + Send { @@ -818,7 +803,7 @@ impl PrincipalManager for Server { actions.push(PrincipalUpdate { action: PrincipalAction::RemoveItem, field: PrincipalField::Secrets, - value: PrincipalValue::String(CompactString::new("")), + value: PrincipalValue::String(String::new()), }); (PrincipalAction::AddItem, password) @@ -828,13 +813,12 @@ impl PrincipalManager for Server { PrincipalAction::RemoveItem, url.unwrap_or_else(|| "otpauth://".into()), ), - AccountAuthRequest::AddAppPassword { name, password } => ( - PrincipalAction::AddItem, - format_compact!("$app${name}${password}"), - ), + AccountAuthRequest::AddAppPassword { name, password } => { + (PrincipalAction::AddItem, format!("$app${name}${password}")) + } AccountAuthRequest::RemoveAppPassword { name } => ( PrincipalAction::RemoveItem, - format_compact!("$app${}", name.unwrap_or_default()), + format!("$app${}", name.unwrap_or_default()), ), }; diff --git a/crates/http/src/management/queue.rs b/crates/http/src/management/queue.rs index 503e894b..a3e2ae66 100644 --- a/crates/http/src/management/queue.rs +++ b/crates/http/src/management/queue.rs @@ -8,7 +8,7 @@ use std::{future::Future, sync::atomic::Ordering}; use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD}; use common::{Server, auth::AccessToken, ipc::QueueEvent}; -use compact_str::CompactString; + use directory::{Permission, Type, backend::internal::manage::ManageDirectory}; use hyper::Method; use mail_auth::{ @@ -134,7 +134,7 @@ impl QueueManagement for Server { // SPDX-License-Identifier: LicenseRef-SEL // Limit to tenant domains - let mut tenant_domains: Option> = None; + let mut tenant_domains: Option> = None; #[cfg(feature = "enterprise")] if self.core.is_enterprise_edition() { if let Some(tenant) = access_token.tenant { @@ -466,7 +466,7 @@ impl QueueManagement for Server { match report_id { QueueClass::DmarcReportHeader(event) if tenant_domains.as_ref().is_none_or(|domains| { - domains.iter().any(|dd| dd == event.domain) + domains.iter().any(|dd| dd == &event.domain) }) => { let mut rua = Vec::new(); @@ -479,7 +479,7 @@ impl QueueManagement for Server { } QueueClass::TlsReportHeader(event) if tenant_domains.as_ref().is_none_or(|domains| { - domains.iter().any(|dd| dd == event.domain) + domains.iter().any(|dd| dd == &event.domain) }) => { let mut rua = Vec::new(); @@ -539,7 +539,7 @@ impl QueueManagement for Server { let result = match report_id { QueueClass::DmarcReportHeader(event) if tenant_domains.as_ref().is_none_or(|domains| { - domains.iter().any(|dd| dd == event.domain) + domains.iter().any(|dd| dd == &event.domain) }) => { self.delete_dmarc_report(event).await; @@ -547,7 +547,7 @@ impl QueueManagement for Server { } QueueClass::TlsReportHeader(event) if tenant_domains.as_ref().is_none_or(|domains| { - domains.iter().any(|dd| dd == event.domain) + domains.iter().any(|dd| dd == &event.domain) }) => { self.delete_tls_report(vec![event]).await; @@ -668,7 +668,7 @@ struct QueuedMessages { async fn fetch_queued_messages( server: &Server, params: &UrlParams<'_>, - tenant_domains: &Option>, + tenant_domains: &Option>, ) -> trc::Result { let text = params.get("text"); let from = params.get("from"); @@ -774,7 +774,7 @@ struct QueuedReports { async fn fetch_queued_reports( server: &Server, params: &UrlParams<'_>, - tenant_domains: &Option>, + tenant_domains: &Option>, ) -> trc::Result { let domain = params.get("domain").map(|d| d.to_lowercase()); let type_ = params.get("type").and_then(|t| match t { @@ -823,7 +823,7 @@ async fn fetch_queued_reports( let event = ReportEvent::deserialize(key)?; if tenant_domains .as_ref() - .is_none_or(|domains| domains.iter().any(|dd| dd == event.domain)) + .is_none_or(|domains| domains.iter().any(|dd| dd == &event.domain)) && event.seq_id != 0 && domain.as_ref().is_none_or(|d| event.domain.contains(d)) { @@ -964,10 +964,10 @@ fn is_zero(num: &i16) -> bool { } trait IsTenantDomain { - fn is_tenant_domain(&self, tenant_domains: &Option>) -> bool; + fn is_tenant_domain(&self, tenant_domains: &Option>) -> bool; } impl IsTenantDomain for ArchivedMessage { - fn is_tenant_domain(&self, tenant_domains: &Option>) -> bool { + fn is_tenant_domain(&self, tenant_domains: &Option>) -> bool { tenant_domains .as_ref() .is_none_or(|domains| self.has_domain(domains)) diff --git a/crates/http/src/management/report.rs b/crates/http/src/management/report.rs index fdc8f8e7..f3f96732 100644 --- a/crates/http/src/management/report.rs +++ b/crates/http/src/management/report.rs @@ -7,7 +7,7 @@ use std::future::Future; use common::{Server, auth::AccessToken}; -use compact_str::CompactString; + use directory::{Permission, Type, backend::internal::manage::ManageDirectory}; use hyper::Method; use mail_auth::report::{ @@ -52,7 +52,7 @@ impl ManageReports for Server { // SPDX-License-Identifier: LicenseRef-SEL // Limit to tenant domains - let mut tenant_domains: Option> = None; + let mut tenant_domains: Option> = None; #[cfg(feature = "enterprise")] if self.core.is_enterprise_edition() { if let Some(tenant) = access_token.tenant { @@ -297,7 +297,7 @@ async fn fetch_incoming_reports( server: &Server, class: &str, params: &UrlParams<'_>, - tenant_domains: &Option>, + tenant_domains: &Option>, ) -> trc::Result { let filter = params.get("text"); let page: usize = params.parse::("page").unwrap_or_default(); diff --git a/crates/http/src/management/spam.rs b/crates/http/src/management/spam.rs index c2af5b12..94ea82e8 100644 --- a/crates/http/src/management/spam.rs +++ b/crates/http/src/management/spam.rs @@ -7,6 +7,7 @@ use std::net::IpAddr; use common::{Server, auth::AccessToken, config::spamfilter::SpamFilterAction, psl}; + use compact_str::CompactString; use directory::{ Permission, diff --git a/crates/http/src/request.rs b/crates/http/src/request.rs index 4678aba2..2d2291c4 100644 --- a/crates/http/src/request.rs +++ b/crates/http/src/request.rs @@ -233,10 +233,7 @@ impl ParseHttp for Server { self.authenticate_headers(&req, &session, false).await?; return self - .handle_session_resource( - ctx.resolve_response_url(self).await.into(), - access_token, - ) + .handle_session_resource(ctx.resolve_response_url(self).await, access_token) .await .map(|s| s.into_http_response()); } diff --git a/crates/imap-proto/src/parser/acl.rs b/crates/imap-proto/src/parser/acl.rs index 3c420fc2..a6747ff0 100644 --- a/crates/imap-proto/src/parser/acl.rs +++ b/crates/imap-proto/src/parser/acl.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ @@ -43,17 +45,17 @@ impl Request { let mailbox_name = utf7_maybe_decode( tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing mailbox name."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing mailbox name."))? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ); let identifier = if has_identifier { tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing identifier."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing identifier."))? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? .into() } else { None @@ -62,10 +64,10 @@ impl Request { ModRights::parse( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing rights."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing rights."))? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? .into() } else { None diff --git a/crates/imap-proto/src/parser/append.rs b/crates/imap-proto/src/parser/append.rs index 0a59de4b..834b4188 100644 --- a/crates/imap-proto/src/parser/append.rs +++ b/crates/imap-proto/src/parser/append.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ @@ -35,7 +37,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ); let mut messages = Vec::new(); @@ -61,7 +63,7 @@ impl Request { State::UTF8 => State::UTF8Data, _ => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid opening parenthesis found.", )); } @@ -70,7 +72,7 @@ impl Request { Token::ParenthesisClose => match state { State::None | State::UTF8 => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid closing parenthesis found.", )); } @@ -93,7 +95,7 @@ impl Request { message.received_at = Some(date_time); } else { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Failed to parse received time.", )); } @@ -105,12 +107,12 @@ impl Request { State::Flags => { message.flags.push( Flag::parse_imap(value) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } State::UTF8 => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Expected parenthesis after UTF8.", )); } @@ -119,13 +121,13 @@ impl Request { message.message = value; } else { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid parameter after message literal.", )); } } }, - _ => return Err(bad(self.tag.to_string(), "Invalid arguments.")), + _ => return Err(bad(self.tag.to_compact_string(), "Invalid arguments.")), } } diff --git a/crates/imap-proto/src/parser/authenticate.rs b/crates/imap-proto/src/parser/authenticate.rs index b4ba120a..6ab0ded8 100644 --- a/crates/imap-proto/src/parser/authenticate.rs +++ b/crates/imap-proto/src/parser/authenticate.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::authenticate::{self, Mechanism}, @@ -16,7 +18,7 @@ impl Request { let mut tokens = self.tokens.into_iter(); Ok(authenticate::Arguments { mechanism: Mechanism::parse(&tokens.next().unwrap().unwrap_bytes()) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, params: tokens .filter_map(|token| token.unwrap_string().ok()) .collect(), diff --git a/crates/imap-proto/src/parser/copy_move.rs b/crates/imap-proto/src/parser/copy_move.rs index 5ffa5c09..42a18ad4 100644 --- a/crates/imap-proto/src/parser/copy_move.rs +++ b/crates/imap-proto/src/parser/copy_move.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ProtocolVersion, copy_move}, @@ -22,16 +24,16 @@ impl Request { sequence_set: parse_sequence_set( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing sequence set."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing sequence set."))? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, mailbox_name: utf7_maybe_decode( tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing mailbox name."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing mailbox name."))? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, diff --git a/crates/imap-proto/src/parser/create.rs b/crates/imap-proto/src/parser/create.rs index 80879219..1625ee82 100644 --- a/crates/imap-proto/src/parser/create.rs +++ b/crates/imap-proto/src/parser/create.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::{CompactString, ToCompactString, format_compact}; + use crate::{ Command, protocol::{ProtocolVersion, create, list::Attribute}, @@ -20,21 +22,27 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ); let mailbox_role = if let Some(Token::ParenthesisOpen) = tokens.next() { match tokens.next() { Some(Token::Argument(param)) if param.eq_ignore_ascii_case(b"USE") => (), _ => { - return Err(bad(self.tag, "Failed to parse, expected 'USE'.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Failed to parse, expected 'USE'.", + )); } } if tokens .next() .is_none_or(|token| !token.is_parenthesis_open()) { - return Err(bad(self.tag, "Expected '(' after 'USE'.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Expected '(' after 'USE'.", + )); } match tokens.next() { Some(Token::Argument(value)) => { @@ -52,14 +60,14 @@ impl Request { Some(Some(tag)) => Some(tag), Some(None) => { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "A mailbox with the \"\\All\" attribute already exists.", )); } None => { return Err(bad( - self.tag, - format!( + CompactString::from_string_buffer(self.tag), + format_compact!( "Special use attribute {:?} is not supported.", String::from_utf8_lossy(&value) ), @@ -68,7 +76,10 @@ impl Request { } } _ => { - return Err(bad(self.tag, "Invalid SPECIAL-USE attribute.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Invalid SPECIAL-USE attribute.", + )); } } } else { diff --git a/crates/imap-proto/src/parser/delete.rs b/crates/imap-proto/src/parser/delete.rs index 180c5cd4..19f3570b 100644 --- a/crates/imap-proto/src/parser/delete.rs +++ b/crates/imap-proto/src/parser/delete.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ProtocolVersion, delete}, @@ -21,7 +23,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, diff --git a/crates/imap-proto/src/parser/enable.rs b/crates/imap-proto/src/parser/enable.rs index 9f5ebe43..d3784b0a 100644 --- a/crates/imap-proto/src/parser/enable.rs +++ b/crates/imap-proto/src/parser/enable.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{capability::Capability, enable}, @@ -18,7 +20,7 @@ impl Request { for capability in self.tokens { capabilities.push( Capability::parse(&capability.unwrap_bytes()) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } Ok(enable::Arguments { diff --git a/crates/imap-proto/src/parser/fetch.rs b/crates/imap-proto/src/parser/fetch.rs index 5a288f7c..0549fb84 100644 --- a/crates/imap-proto/src/parser/fetch.rs +++ b/crates/imap-proto/src/parser/fetch.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use std::iter::Peekable; use std::vec::IntoIter; -use compact_str::CompactString; +use compact_str::{CompactString, ToCompactString, format_compact}; use crate::{ Command, @@ -30,10 +30,10 @@ impl Request { let sequence_set = parse_sequence_set( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing sequence set."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing sequence set."))? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; let mut in_parentheses = false; @@ -90,7 +90,7 @@ impl Request { let rfc822 = tokens .next() .ok_or_else(|| { - bad(self.tag.to_string(), "Missing RFC822 parameter.") + bad(self.tag.to_compact_string(), "Missing RFC822 parameter.") })? .unwrap_bytes(); if rfc822.eq_ignore_ascii_case(b"HEADER") { @@ -101,8 +101,8 @@ impl Request { Attribute::Rfc822Text } else { return Err(bad( - self.tag, - format!( + CompactString::from_string_buffer(self.tag), + format_compact!( "Invalid RFC822 parameter {:?}.", String::from_utf8_lossy(&rfc822) ), @@ -126,13 +126,13 @@ impl Request { .is_none_or( |token| !token.eq_ignore_ascii_case(b"PEEK")) { return Err(bad( - self.tag.clone(), + self.tag.to_compact_string(), "Expected 'PEEK' after '.'.", )); } if tokens.next().is_none_or( |token| !token.is_bracket_open()) { return Err(bad( - self.tag.clone(), + self.tag.to_compact_string(), "Expected '[' after 'BODY.PEEK'", )); } @@ -162,7 +162,7 @@ impl Request { !token.eq_ignore_ascii_case(b"FIELDS") }) { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Expected 'FIELDS' after 'HEADER.'.", )); } @@ -172,7 +172,7 @@ impl Request { !token.eq_ignore_ascii_case(b"NOT") }) { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Expected 'NOT' after 'HEADER.FIELDS.'.", )); } @@ -185,7 +185,7 @@ impl Request { .is_none_or( |token| !token.is_parenthesis_open()) { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Expected '(' after 'HEADER.FIELDS'.", )); } @@ -194,13 +194,13 @@ impl Request { match token { Token::ParenthesisClose => break, Token::Argument(value) => { - fields.push(CompactString::from_utf8(value).map_err( - |_| bad(self.tag.clone(), "Invalid UTF-8 in header field name."), + fields.push(String::from_utf8(value).map_err( + |_| bad(self.tag.to_compact_string(),"Invalid UTF-8 in header field name."), )?); } _ => { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Expected field name.", )) } @@ -220,7 +220,7 @@ impl Request { } else { Section::Part { num: parse_number::(&value) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, } }; sections.push(section); @@ -228,8 +228,8 @@ impl Request { Token::Dot => (), _ => { return Err(bad( - self.tag, - format!( + CompactString::from_string_buffer(self.tag), + format_compact!( "Invalid token {:?} found in section-spect.", token ), @@ -242,7 +242,7 @@ impl Request { peek: is_peek, sections, partial: parse_partial(&mut tokens) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, }); }, "BINARY" => { @@ -251,7 +251,7 @@ impl Request { let param = tokens .next() .ok_or({ - bad(self.tag.clone(), "Missing parameter after 'BINARY.'.") + bad(self.tag.to_compact_string(),"Missing parameter after 'BINARY.'.") })? .unwrap_bytes(); if param.eq_ignore_ascii_case(b"PEEK") { @@ -260,7 +260,7 @@ impl Request { (false, true) } else { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Expected 'PEEK' or 'SIZE' after 'BINARY.'.", )); } @@ -270,7 +270,7 @@ impl Request { // Parse section-part if tokens.next().is_none_or( |token| !token.is_bracket_open()) { - return Err(bad(self.tag.to_string(), "Expected '[' after 'BINARY'.")); + return Err(bad(self.tag.to_compact_string(), "Expected '[' after 'BINARY'.")); } let mut sections = Vec::new(); while let Some(token) = tokens.next() { @@ -278,15 +278,15 @@ impl Request { Token::Argument(value) => { sections.push( parse_number::(&value) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } Token::Dot => (), Token::BracketClose => break, _ => { return Err(bad( - self.tag, - format!( + CompactString::from_string_buffer(self.tag), + format_compact!( "Expected part section integer, got {:?}.", token.to_string() ), @@ -299,7 +299,7 @@ impl Request { peek: is_peek, sections, partial: parse_partial(&mut tokens) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, } } else { Attribute::BinarySize { sections } @@ -338,8 +338,8 @@ impl Request { }, _ => { return Err(bad( - self.tag, - format!("Invalid attribute {:?}", String::from_utf8_lossy(&value)), + CompactString::from_string_buffer(self.tag), + format_compact!("Invalid attribute {:?}", String::from_utf8_lossy(&value)), )); } ); @@ -352,20 +352,26 @@ impl Request { if !in_parentheses { in_parentheses = true; } else { - return Err(bad(self.tag.to_string(), "Unexpected parenthesis open.")); + return Err(bad( + self.tag.to_compact_string(), + "Unexpected parenthesis open.", + )); } } Token::ParenthesisClose => { if in_parentheses { break; } else { - return Err(bad(self.tag.to_string(), "Unexpected parenthesis close.")); + return Err(bad( + self.tag.to_compact_string(), + "Unexpected parenthesis close.", + )); } } _ => { return Err(bad( - self.tag, - format!("Invalid fetch argument {:?}.", token.to_string()), + CompactString::from_string_buffer(self.tag), + format_compact!("Invalid fetch argument {:?}.", token.to_string()), )); } } @@ -383,11 +389,14 @@ impl Request { &tokens .next() .ok_or_else(|| { - bad(self.tag.to_string(), "Missing CHANGEDSINCE parameter.") + bad( + self.tag.to_compact_string(), + "Missing CHANGEDSINCE parameter.", + ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? .into(); } Token::Argument(param) if param.eq_ignore_ascii_case(b"VANISHED") => { @@ -398,8 +407,8 @@ impl Request { } _ => { return Err(bad( - self.tag.clone(), - format!("Unsupported parameter '{}'.", token.to_string()), + self.tag.to_compact_string(), + format_compact!("Unsupported parameter '{}'.", token), )); } } @@ -415,7 +424,10 @@ impl Request { include_vanished, }) } else { - Err(bad(self.tag, "No data items to fetch specified.")) + Err(bad( + CompactString::from_string_buffer(self.tag), + "No data items to fetch specified.", + )) } } } diff --git a/crates/imap-proto/src/parser/list.rs b/crates/imap-proto/src/parser/list.rs index a3bf1bf7..802c52f0 100644 --- a/crates/imap-proto/src/parser/list.rs +++ b/crates/imap-proto/src/parser/list.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::{CompactString, ToCompactString}; + use crate::{ Command, protocol::{ @@ -27,13 +29,13 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, mailbox_name: utf7_maybe_decode( tokens .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, @@ -53,12 +55,12 @@ impl Request { Token::Argument(value) => { selection_options.push( SelectionOption::parse(&value) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } _ => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid selection option argument.", )); } @@ -66,18 +68,20 @@ impl Request { } tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing reference name."))? + .ok_or_else(|| { + bad(self.tag.to_compact_string(), "Missing reference name.") + })? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? } token => token .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, }; match tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing mailbox name."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing mailbox name."))? { Token::ParenthesisOpen => { while let Some(token) = tokens.next() { @@ -87,7 +91,7 @@ impl Request { mailbox_name.push( token .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } } @@ -97,7 +101,7 @@ impl Request { mailbox_name.push(utf7_maybe_decode( token .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, )); } @@ -112,7 +116,7 @@ impl Request { .is_none_or(|token| !token.is_parenthesis_open()) { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid return option, expected parenthesis.", )); } @@ -122,14 +126,14 @@ impl Request { Token::ParenthesisClose => break, Token::Argument(value) => { let mut return_option = ReturnOption::parse(&value) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; if let ReturnOption::Status(status) = &mut return_option { if tokens .next() .is_none_or(|token| !token.is_parenthesis_open()) { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Invalid return option, expected parenthesis after STATUS.", )); } @@ -137,15 +141,13 @@ impl Request { match token { Token::ParenthesisClose => break, Token::Argument(value) => { - status.push( - Status::parse(&value).map_err(|v| { - bad(self.tag.to_string(), v) - })?, - ); + status.push(Status::parse(&value).map_err( + |v| bad(self.tag.to_compact_string(), v), + )?); } _ => { return Err(bad( - self.tag, + CompactString::from_string_buffer(self.tag), "Invalid status return option argument.", )); } @@ -156,7 +158,7 @@ impl Request { } _ => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid return option argument.", )); } diff --git a/crates/imap-proto/src/parser/login.rs b/crates/imap-proto/src/parser/login.rs index 5c4b82fd..313280bd 100644 --- a/crates/imap-proto/src/parser/login.rs +++ b/crates/imap-proto/src/parser/login.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::login, @@ -20,12 +22,12 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, password: tokens .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, tag: self.tag, }) } diff --git a/crates/imap-proto/src/parser/lsub.rs b/crates/imap-proto/src/parser/lsub.rs index 529611bb..4ee69e7e 100644 --- a/crates/imap-proto/src/parser/lsub.rs +++ b/crates/imap-proto/src/parser/lsub.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ @@ -22,15 +24,15 @@ impl Request { Ok(list::Arguments::Extended { reference_name: tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing reference name."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing reference name."))? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, mailbox_name: vec![utf7_maybe_decode( tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing mailbox name."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing mailbox name."))? .unwrap_string() - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ProtocolVersion::Rev1, )], selection_options: vec![SelectionOption::Subscribed], diff --git a/crates/imap-proto/src/parser/mod.rs b/crates/imap-proto/src/parser/mod.rs index 66adb86e..0c6be3a6 100644 --- a/crates/imap-proto/src/parser/mod.rs +++ b/crates/imap-proto/src/parser/mod.rs @@ -28,7 +28,6 @@ pub mod thread; use std::{borrow::Cow, str::FromStr}; use chrono::{DateTime, NaiveDate}; -use compact_str::CompactString; use crate::{ Command, @@ -112,7 +111,7 @@ impl Flag { if let Some(flag) = flag { Ok(flag) } else { - CompactString::from_utf8(value) + String::from_utf8(value) .map_err(|_| Cow::from("Invalid UTF-8.")) .map(Flag::Keyword) } @@ -137,9 +136,9 @@ impl Flag { "$forwarded" => Flag::Forwarded, "$mdnsent" => Flag::MDNSent, ) - .unwrap_or_else(|| Flag::Keyword(value.into())) + .unwrap_or_else(|| Flag::Keyword(value)) } else { - let mut keyword = CompactString::with_capacity(value.len()); + let mut keyword = String::with_capacity(value.len()); for c in value.chars() { if c.is_ascii_alphanumeric() { keyword.push(c); diff --git a/crates/imap-proto/src/parser/quota.rs b/crates/imap-proto/src/parser/quota.rs index 2b0c0e07..47ffb0c5 100644 --- a/crates/imap-proto/src/parser/quota.rs +++ b/crates/imap-proto/src/parser/quota.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ProtocolVersion, quota}, @@ -21,7 +23,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, @@ -40,7 +42,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, tag: self.tag, }), 0 => Err(self.into_error("Missing quota root.")), diff --git a/crates/imap-proto/src/parser/rename.rs b/crates/imap-proto/src/parser/rename.rs index 2f0fc6f6..05f5309a 100644 --- a/crates/imap-proto/src/parser/rename.rs +++ b/crates/imap-proto/src/parser/rename.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ProtocolVersion, rename}, @@ -22,7 +24,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), new_mailbox_name: utf7_maybe_decode( @@ -30,7 +32,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, diff --git a/crates/imap-proto/src/parser/search.rs b/crates/imap-proto/src/parser/search.rs index 5023bd94..9f2af4bb 100644 --- a/crates/imap-proto/src/parser/search.rs +++ b/crates/imap-proto/src/parser/search.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use std::iter::Peekable; use std::vec::IntoIter; -use compact_str::CompactString; +use compact_str::ToCompactString; use mail_parser::decoders::charsets::DecoderFnc; use mail_parser::decoders::charsets::map::charset_decoder; @@ -38,14 +38,14 @@ impl Request { tokens.next(); is_esearch = true; result_options = parse_result_options(&mut tokens) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; } Some(Token::Argument(value)) if value.eq_ignore_ascii_case(b"charset") => { tokens.next(); decoder = charset_decoder( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing charset."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing charset."))? .unwrap_bytes(), ); } @@ -53,11 +53,14 @@ impl Request { } } - let filter = - parse_filters(&mut tokens, decoder).map_err(|v| bad(self.tag.to_string(), v))?; + let filter = parse_filters(&mut tokens, decoder) + .map_err(|v| bad(self.tag.to_compact_string(), v))?; match filter.len() { - 0 => Err(bad(self.tag.to_string(), "No filters found in command.")), + 0 => Err(bad( + self.tag.to_compact_string(), + "No filters found in command.", + )), _ => Ok(search::Arguments { tag: self.tag, result_options, @@ -374,7 +377,7 @@ pub fn parse_filters( } Some(token) => { return Err( - format!("Unsupported MODSEQ parameter '{}'.", token.to_string()).into() + format!("Unsupported MODSEQ parameter '{}'.", token).into() ); } None => { @@ -500,16 +503,16 @@ pub fn parse_filters( pub fn decode_argument( tokens: &mut Peekable>, decoder: Option, -) -> super::Result { +) -> super::Result { let argument = tokens .next() .ok_or_else(|| Cow::from("Expected string."))? .unwrap_bytes(); if let Some(decoder) = decoder { - Ok(decoder(&argument).into()) + Ok(decoder(&argument)) } else { - Ok(CompactString::from_utf8(argument).map_err(|_| Cow::from("Invalid UTF-8 argument."))?) + Ok(String::from_utf8(argument).map_err(|_| Cow::from("Invalid UTF-8 argument."))?) } } diff --git a/crates/imap-proto/src/parser/select.rs b/crates/imap-proto/src/parser/select.rs index 1004dafa..2bb3fecb 100644 --- a/crates/imap-proto/src/parser/select.rs +++ b/crates/imap-proto/src/parser/select.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::{CompactString, ToCompactString, format_compact}; + use crate::{ Command, protocol::{ @@ -27,7 +29,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ); @@ -46,7 +48,10 @@ impl Request { .next() .is_none_or(|token| !token.is_parenthesis_open()) { - return Err(bad(self.tag, "Expected '(' after 'QRESYNC'.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Expected '(' after 'QRESYNC'.", + )); } let uid_validity = parse_number::( @@ -54,32 +59,32 @@ impl Request { .next() .ok_or_else(|| { bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Missing uidvalidity parameter for QRESYNC.", ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; let modseq = parse_number::( &tokens .next() .ok_or_else(|| { bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Missing modseq parameter for QRESYNC.", ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; let mut known_uids = None; let mut seq_match = None; let has_seq_match = match tokens.peek() { Some(Token::Argument(value)) => { known_uids = parse_sequence_set(value) - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? .into(); tokens.next(); if matches!(tokens.peek(), Some(Token::ParenthesisOpen)) { @@ -103,31 +108,34 @@ impl Request { .next() .ok_or_else(|| { bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Missing known-sequence-set parameter for QRESYNC.", ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, parse_sequence_set( &tokens .next() .ok_or_else(|| { bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Missing known-uid-set parameter for QRESYNC.", ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, )); if tokens .next() .is_none_or(|token| !token.is_parenthesis_close()) { - return Err(bad(self.tag, "Missing ')' for 'QRESYNC'.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Missing ')' for 'QRESYNC'.", + )); } } @@ -135,7 +143,10 @@ impl Request { .next() .is_none_or(|token| !token.is_parenthesis_close()) { - return Err(bad(self.tag, "Missing ')' for 'QRESYNC'.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Missing ')' for 'QRESYNC'.", + )); } qresync = QResync { @@ -151,8 +162,8 @@ impl Request { } _ => { return Err(bad( - self.tag, - format!("Unexpected value '{}'.", token.to_string()), + CompactString::from_string_buffer(self.tag), + format_compact!("Unexpected value '{}'.", token), )); } } @@ -160,8 +171,8 @@ impl Request { } Some(token) => { return Err(bad( - self.tag, - format!("Unexpected value '{}'.", token.to_string()), + CompactString::from_string_buffer(self.tag), + format_compact!("Unexpected value '{}'.", token), )); } None => (), diff --git a/crates/imap-proto/src/parser/sort.rs b/crates/imap-proto/src/parser/sort.rs index 16d9bceb..a55c581e 100644 --- a/crates/imap-proto/src/parser/sort.rs +++ b/crates/imap-proto/src/parser/sort.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; use mail_parser::decoders::charsets::map::charset_decoder; use crate::{ @@ -28,7 +29,8 @@ impl Request { Some(Token::Argument(value)) if value.eq_ignore_ascii_case(b"return") => { tokens.next(); ( - parse_result_options(&mut tokens).map_err(|v| bad(self.tag.to_string(), v))?, + parse_result_options(&mut tokens) + .map_err(|v| bad(self.tag.to_compact_string(), v))?, true, ) } @@ -40,7 +42,7 @@ impl Request { .is_none_or(|token| !token.is_parenthesis_open()) { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Expected sort criteria between parentheses.", )); } @@ -54,31 +56,40 @@ impl Request { is_ascending = false; } else { sort.push(Comparator { - sort: Sort::parse(&value).map_err(|v| bad(self.tag.to_string(), v))?, + sort: Sort::parse(&value) + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ascending: is_ascending, }); is_ascending = true; } } - _ => return Err(bad(self.tag.to_string(), "Invalid result option argument.")), + _ => { + return Err(bad( + self.tag.to_compact_string(), + "Invalid result option argument.", + )); + } } } if sort.is_empty() { - return Err(bad(self.tag.to_string(), "Missing sort criteria.")); + return Err(bad(self.tag.to_compact_string(), "Missing sort criteria.")); } let decoder = charset_decoder( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing charset."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing charset."))? .unwrap_bytes(), ); - let filter = - parse_filters(&mut tokens, decoder).map_err(|v| bad(self.tag.to_string(), v))?; + let filter = parse_filters(&mut tokens, decoder) + .map_err(|v| bad(self.tag.to_compact_string(), v))?; match filter.len() { - 0 => Err(bad(self.tag.to_string(), "No filters found in command.")), + 0 => Err(bad( + self.tag.to_compact_string(), + "No filters found in command.", + )), _ => Ok(Arguments { sort: sort.into(), result_options, diff --git a/crates/imap-proto/src/parser/status.rs b/crates/imap-proto/src/parser/status.rs index 714a27f9..9610e17d 100644 --- a/crates/imap-proto/src/parser/status.rs +++ b/crates/imap-proto/src/parser/status.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::{CompactString, ToCompactString}; + use crate::Command; use crate::protocol::status::Status; use crate::protocol::{ProtocolVersion, status}; @@ -21,7 +23,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ); let mut items = Vec::with_capacity(len - 2); @@ -31,7 +33,7 @@ impl Request { .is_none_or(|token| !token.is_parenthesis_open()) { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Expected parenthesis after mailbox name.", )); } @@ -42,12 +44,13 @@ impl Request { Token::ParenthesisClose => break, Token::Argument(value) => { items.push( - Status::parse(&value).map_err(|v| bad(self.tag.to_string(), v))?, + Status::parse(&value) + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } _ => { return Err(bad( - self.tag.to_string(), + self.tag.to_compact_string(), "Invalid status return option argument.", )); } @@ -61,7 +64,10 @@ impl Request { items, }) } else { - Err(bad(self.tag, "At least one status item is required.")) + Err(bad( + CompactString::from_string_buffer(self.tag), + "At least one status item is required.", + )) } } } diff --git a/crates/imap-proto/src/parser/store.rs b/crates/imap-proto/src/parser/store.rs index 767c14b4..0692711f 100644 --- a/crates/imap-proto/src/parser/store.rs +++ b/crates/imap-proto/src/parser/store.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::{CompactString, ToCompactString, format_compact}; + use crate::{ Command, protocol::{ @@ -23,10 +25,10 @@ impl Request { let sequence_set = parse_sequence_set( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing sequence set."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing sequence set."))? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; let mut unchanged_since = None; // CONDSTORE parameters @@ -39,11 +41,14 @@ impl Request { &tokens .next() .ok_or_else(|| { - bad(self.tag.to_string(), "Missing UNCHANGEDSINCE parameter.") + bad( + self.tag.to_compact_string(), + "Missing UNCHANGEDSINCE parameter.", + ) })? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))? + .map_err(|v| bad(self.tag.to_compact_string(), v))? .into(); } Token::ParenthesisClose => { @@ -51,8 +56,8 @@ impl Request { } _ => { return Err(bad( - self.tag.to_string(), - format!("Unsupported parameter '{}'.", token.to_string()), + self.tag.to_compact_string(), + format_compact!("Unsupported parameter '{}'.", token), )); } } @@ -62,7 +67,12 @@ impl Request { // Operation let operation = tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing message data item name."))? + .ok_or_else(|| { + bad( + self.tag.to_compact_string(), + "Missing message data item name.", + ) + })? .unwrap_bytes(); let (is_silent, operation) = hashify::tiny_map_ignore_case!(operation.as_slice(), "FLAGS" => (false, Operation::Set), @@ -74,8 +84,8 @@ impl Request { ) .ok_or_else(|| { bad( - self.tag.to_string(), - format!( + self.tag.to_compact_string(), + format_compact!( "Unsupported message data item name: {:?}", String::from_utf8_lossy(&operation) ), @@ -86,30 +96,36 @@ impl Request { let mut keywords = Vec::new(); match tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing flags to set."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing flags to set."))? { Token::ParenthesisOpen => { for token in tokens { match token { Token::Argument(flag) => { keywords.push( - Flag::parse_imap(flag).map_err(|v| bad(self.tag.to_string(), v))?, + Flag::parse_imap(flag) + .map_err(|v| bad(self.tag.to_compact_string(), v))?, ); } Token::ParenthesisClose => { break; } _ => { - return Err(bad(self.tag.to_string(), "Unsupported flag.")); + return Err(bad(self.tag.to_compact_string(), "Unsupported flag.")); } } } } Token::Argument(flag) => { - keywords.push(Flag::parse_imap(flag).map_err(|v| bad(self.tag.to_string(), v))?); + keywords.push( + Flag::parse_imap(flag).map_err(|v| bad(self.tag.to_compact_string(), v))?, + ); } _ => { - return Err(bad(self.tag, "Invalid flags parameter.")); + return Err(bad( + CompactString::from_string_buffer(self.tag), + "Invalid flags parameter.", + )); } } @@ -123,7 +139,7 @@ impl Request { unchanged_since, }) } else { - Err(bad(self.tag.to_string(), "Missing flags to set.")) + Err(bad(self.tag.to_compact_string(), "Missing flags to set.")) } } } diff --git a/crates/imap-proto/src/parser/subscribe.rs b/crates/imap-proto/src/parser/subscribe.rs index 24f9bd54..1d857d93 100644 --- a/crates/imap-proto/src/parser/subscribe.rs +++ b/crates/imap-proto/src/parser/subscribe.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; + use crate::{ Command, protocol::{ProtocolVersion, subscribe}, @@ -21,7 +23,7 @@ impl Request { .next() .unwrap() .unwrap_string() - .map_err(|v| bad(self.tag.clone(), v))?, + .map_err(|v| bad(self.tag.to_compact_string(), v))?, version, ), tag: self.tag, diff --git a/crates/imap-proto/src/parser/thread.rs b/crates/imap-proto/src/parser/thread.rs index 28e439cd..eae3c91f 100644 --- a/crates/imap-proto/src/parser/thread.rs +++ b/crates/imap-proto/src/parser/thread.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::ToCompactString; use mail_parser::decoders::charsets::map::charset_decoder; use crate::{ @@ -25,22 +26,25 @@ impl Request { let algorithm = Algorithm::parse( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing threading algorithm."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing threading algorithm."))? .unwrap_bytes(), ) - .map_err(|v| bad(self.tag.to_string(), v))?; + .map_err(|v| bad(self.tag.to_compact_string(), v))?; let decoder = charset_decoder( &tokens .next() - .ok_or_else(|| bad(self.tag.to_string(), "Missing charset."))? + .ok_or_else(|| bad(self.tag.to_compact_string(), "Missing charset."))? .unwrap_bytes(), ); - let filter = - parse_filters(&mut tokens, decoder).map_err(|v| bad(self.tag.to_string(), v))?; + let filter = parse_filters(&mut tokens, decoder) + .map_err(|v| bad(self.tag.to_compact_string(), v))?; match filter.len() { - 0 => Err(bad(self.tag.to_string(), "No filters found in command.")), + 0 => Err(bad( + self.tag.to_compact_string(), + "No filters found in command.", + )), _ => Ok(thread::Arguments { algorithm, filter, diff --git a/crates/imap-proto/src/protocol/acl.rs b/crates/imap-proto/src/protocol/acl.rs index 8dddabc2..850061ed 100644 --- a/crates/imap-proto/src/protocol/acl.rs +++ b/crates/imap-proto/src/protocol/acl.rs @@ -35,7 +35,7 @@ use std::fmt::Display; -use compact_str::CompactString; + use jmap_proto::types::acl::Acl; use crate::utf7::utf7_encode; @@ -72,28 +72,28 @@ pub enum ModRightsOp { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, - pub identifier: Option, + pub tag: String, + pub mailbox_name: String, + pub identifier: Option, pub mod_rights: Option, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct GetAclResponse { - pub mailbox_name: CompactString, - pub permissions: Vec<(CompactString, Vec)>, + pub mailbox_name: String, + pub permissions: Vec<(String, Vec)>, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ListRightsResponse { - pub mailbox_name: CompactString, - pub identifier: CompactString, + pub mailbox_name: String, + pub identifier: String, pub permissions: Vec>, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct MyRightsResponse { - pub mailbox_name: CompactString, + pub mailbox_name: String, pub rights: Vec, } @@ -249,14 +249,14 @@ impl From for Acl { #[cfg(test)] mod tests { - use compact_str::CompactString; + use crate::protocol::acl::{GetAclResponse, ListRightsResponse, MyRightsResponse, Rights}; #[test] fn serialize_acl() { assert_eq!( - CompactString::from_utf8( + String::from_utf8( GetAclResponse { mailbox_name: "INBOX".into(), permissions: vec![ @@ -290,7 +290,7 @@ mod tests { ); assert_eq!( - CompactString::from_utf8( + String::from_utf8( ListRightsResponse { mailbox_name: "Deleted Items".into(), identifier: "Fred".into(), @@ -307,7 +307,7 @@ mod tests { ); assert_eq!( - CompactString::from_utf8( + String::from_utf8( MyRightsResponse { mailbox_name: "Important".into(), rights: vec![Rights::Lookup, Rights::Read, Rights::DeleteMailbox] diff --git a/crates/imap-proto/src/protocol/append.rs b/crates/imap-proto/src/protocol/append.rs index f42671d3..343242e6 100644 --- a/crates/imap-proto/src/protocol/append.rs +++ b/crates/imap-proto/src/protocol/append.rs @@ -4,14 +4,14 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::Flag; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, pub messages: Vec, } diff --git a/crates/imap-proto/src/protocol/authenticate.rs b/crates/imap-proto/src/protocol/authenticate.rs index f165b717..d85dc729 100644 --- a/crates/imap-proto/src/protocol/authenticate.rs +++ b/crates/imap-proto/src/protocol/authenticate.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub mechanism: Mechanism, - pub params: Vec, + pub params: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/imap-proto/src/protocol/copy_move.rs b/crates/imap-proto/src/protocol/copy_move.rs index 42ca7192..3657a608 100644 --- a/crates/imap-proto/src/protocol/copy_move.rs +++ b/crates/imap-proto/src/protocol/copy_move.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::Sequence; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub sequence_set: Sequence, - pub mailbox_name: CompactString, + pub mailbox_name: String, } diff --git a/crates/imap-proto/src/protocol/create.rs b/crates/imap-proto/src/protocol/create.rs index cbc41da4..064feeb3 100644 --- a/crates/imap-proto/src/protocol/create.rs +++ b/crates/imap-proto/src/protocol/create.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::list::Attribute; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, pub mailbox_role: Option, } diff --git a/crates/imap-proto/src/protocol/delete.rs b/crates/imap-proto/src/protocol/delete.rs index e6a78de5..1df766da 100644 --- a/crates/imap-proto/src/protocol/delete.rs +++ b/crates/imap-proto/src/protocol/delete.rs @@ -4,10 +4,10 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, } diff --git a/crates/imap-proto/src/protocol/enable.rs b/crates/imap-proto/src/protocol/enable.rs index 740ca972..379b6aa1 100644 --- a/crates/imap-proto/src/protocol/enable.rs +++ b/crates/imap-proto/src/protocol/enable.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::{ImapResponse, capability::Capability}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub capabilities: Vec, } diff --git a/crates/imap-proto/src/protocol/fetch.rs b/crates/imap-proto/src/protocol/fetch.rs index c8a51edb..9e1f3548 100644 --- a/crates/imap-proto/src/protocol/fetch.rs +++ b/crates/imap-proto/src/protocol/fetch.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; -use compact_str::CompactString; + use mail_parser::DateTime; use super::{ @@ -16,7 +16,7 @@ use super::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub sequence_set: Sequence, pub attributes: Vec, pub changed_since: Option, @@ -69,14 +69,9 @@ pub enum Attribute { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Section { - Part { - num: u32, - }, + Part { num: u32 }, Header, - HeaderFields { - not: bool, - fields: Vec, - }, + HeaderFields { not: bool, fields: Vec }, Text, Mime, } @@ -134,10 +129,10 @@ pub enum DataItem<'x> { modseq: u64, }, EmailId { - email_id: CompactString, + email_id: String, }, ThreadId { - thread_id: CompactString, + thread_id: String, }, } @@ -922,7 +917,7 @@ impl ImapResponse for Response<'_> { #[cfg(test)] mod tests { - use compact_str::CompactString; + use mail_parser::DateTime; use crate::protocol::{Flag, ImapResponse}; @@ -1370,7 +1365,7 @@ mod tests { item.serialize(&mut buf); - assert_eq!(CompactString::from_utf8(buf).unwrap(), expected_response); + assert_eq!(String::from_utf8(buf).unwrap(), expected_response); } } diff --git a/crates/imap-proto/src/protocol/list.rs b/crates/imap-proto/src/protocol/list.rs index ca8820f8..a4268c2c 100644 --- a/crates/imap-proto/src/protocol/list.rs +++ b/crates/imap-proto/src/protocol/list.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use crate::utf7::utf7_encode; @@ -16,14 +16,14 @@ use super::{ #[derive(Debug, Clone, PartialEq, Eq)] pub enum Arguments { Basic { - tag: CompactString, - reference_name: CompactString, - mailbox_name: CompactString, + tag: String, + reference_name: String, + mailbox_name: String, }, Extended { - tag: CompactString, - reference_name: CompactString, - mailbox_name: Vec, + tag: String, + reference_name: String, + mailbox_name: Vec, selection_options: Vec, return_options: Vec, }, @@ -82,12 +82,12 @@ pub enum ChildInfo { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Tag { ChildInfo(Vec), - OldName(CompactString), + OldName(String), } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ListItem { - pub mailbox_name: CompactString, + pub mailbox_name: String, pub attributes: Vec, pub tags: Vec, } @@ -108,7 +108,7 @@ impl Arguments { } } - pub fn unwrap_tag(self) -> CompactString { + pub fn unwrap_tag(self) -> String { match self { Arguments::Basic { tag, .. } => tag, Arguments::Extended { tag, .. } => tag, @@ -196,7 +196,7 @@ impl Tag { } impl ListItem { - pub fn new(name: impl Into) -> Self { + pub fn new(name: impl Into) -> Self { ListItem { mailbox_name: name.into(), attributes: Vec::new(), @@ -277,7 +277,7 @@ impl ImapResponse for Response { #[cfg(test)] mod tests { - use compact_str::CompactString; + use crate::protocol::{ ImapResponse, @@ -341,8 +341,8 @@ mod tests { response.serialize(&mut buf_1, false, false); response.serialize(&mut buf_2, true, false); - let response_v1 = CompactString::from_utf8(buf_1).unwrap(); - let response_v2 = CompactString::from_utf8(buf_2).unwrap(); + let response_v1 = String::from_utf8(buf_1).unwrap(); + let response_v2 = String::from_utf8(buf_2).unwrap(); assert_eq!(response_v2, expected_v2); assert_eq!(response_v1, expected_v1); @@ -391,11 +391,11 @@ mod tests { "* LSUB () \"/\" \"foo\" (\"CHILDINFO\" (\"SUBSCRIBED\"))\r\n", ); - let response_v2 = CompactString::from_utf8(response.clone().serialize()).unwrap(); + let response_v2 = String::from_utf8(response.clone().serialize()).unwrap(); response.is_rev2 = false; response.is_lsub = true; response.status_items.clear(); - let response_v1 = CompactString::from_utf8(response.serialize()).unwrap(); + let response_v1 = String::from_utf8(response.serialize()).unwrap(); assert_eq!(response_v2, expected_v2); assert_eq!(response_v1, expected_v1); diff --git a/crates/imap-proto/src/protocol/login.rs b/crates/imap-proto/src/protocol/login.rs index 7597a000..a7fd8182 100644 --- a/crates/imap-proto/src/protocol/login.rs +++ b/crates/imap-proto/src/protocol/login.rs @@ -4,11 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub username: CompactString, - pub password: CompactString, + pub tag: String, + pub username: String, + pub password: String, } diff --git a/crates/imap-proto/src/protocol/mod.rs b/crates/imap-proto/src/protocol/mod.rs index 042d30b8..847edabc 100644 --- a/crates/imap-proto/src/protocol/mod.rs +++ b/crates/imap-proto/src/protocol/mod.rs @@ -8,6 +8,7 @@ use std::{cmp::Ordering, fmt::Display}; use ahash::AHashSet; use chrono::{DateTime, Utc}; + use compact_str::CompactString; use jmap_proto::types::keyword::{ArchivedKeyword, Keyword}; @@ -240,7 +241,7 @@ pub enum Flag { Deleted, Forwarded, MDNSent, - Keyword(CompactString), + Keyword(String), } impl Flag { diff --git a/crates/imap-proto/src/protocol/namespace.rs b/crates/imap-proto/src/protocol/namespace.rs index 9b0d4d18..8610daa6 100644 --- a/crates/imap-proto/src/protocol/namespace.rs +++ b/crates/imap-proto/src/protocol/namespace.rs @@ -4,12 +4,12 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::{ImapResponse, quoted_string}; pub struct Response { - pub shared_prefix: Option, + pub shared_prefix: Option, } impl ImapResponse for Response { diff --git a/crates/imap-proto/src/protocol/quota.rs b/crates/imap-proto/src/protocol/quota.rs index 366bd911..41e0caa2 100644 --- a/crates/imap-proto/src/protocol/quota.rs +++ b/crates/imap-proto/src/protocol/quota.rs @@ -4,18 +4,18 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::{ImapResponse, capability::QuotaResourceName, quoted_string}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub name: CompactString, + pub tag: String, + pub name: String, } pub struct QuotaItem { - pub name: CompactString, + pub name: String, pub resources: Vec, } @@ -26,7 +26,7 @@ pub struct QuotaResource { } pub struct Response { - pub quota_root_items: Vec, + pub quota_root_items: Vec, pub quota_items: Vec, } diff --git a/crates/imap-proto/src/protocol/rename.rs b/crates/imap-proto/src/protocol/rename.rs index 87e8e804..6a462f47 100644 --- a/crates/imap-proto/src/protocol/rename.rs +++ b/crates/imap-proto/src/protocol/rename.rs @@ -4,11 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, - pub new_mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, + pub new_mailbox_name: String, } diff --git a/crates/imap-proto/src/protocol/search.rs b/crates/imap-proto/src/protocol/search.rs index fef3f4ce..1e193c8f 100644 --- a/crates/imap-proto/src/protocol/search.rs +++ b/crates/imap-proto/src/protocol/search.rs @@ -4,14 +4,14 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use store::fts::{FilterItem, FilterType}; use super::{Flag, Sequence, quoted_string, serialize_sequence}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub is_esearch: bool, pub sort: Option>, pub result_options: Vec, @@ -64,15 +64,15 @@ pub enum Filter { Sequence(Sequence, bool), All, Answered, - Bcc(CompactString), + Bcc(String), Before(i64), - Body(CompactString), - Cc(CompactString), + Body(String), + Cc(String), Deleted, Draft, Flagged, - From(CompactString), - Header(CompactString, CompactString), + From(String), + Header(String, String), Keyword(Flag), Larger(u32), On(i64), @@ -82,9 +82,9 @@ pub enum Filter { SentSince(i64), Since(i64), Smaller(u32), - Subject(CompactString), - Text(CompactString), - To(CompactString), + Subject(String), + Text(String), + To(String), Unanswered, Undeleted, Undraft, @@ -111,8 +111,8 @@ pub enum Filter { ModSeq((u64, ModSeqEntry)), // RFC 8474 - ObjectID - EmailId(CompactString), - ThreadId(CompactString), + EmailId(String), + ThreadId(String), } impl FilterItem for Filter { diff --git a/crates/imap-proto/src/protocol/select.rs b/crates/imap-proto/src/protocol/select.rs index e9fa55e4..0e4357a5 100644 --- a/crates/imap-proto/src/protocol/select.rs +++ b/crates/imap-proto/src/protocol/select.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use crate::{ResponseCode, StatusResponse}; @@ -12,8 +12,8 @@ use super::{ImapResponse, Sequence, list::ListItem}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, pub condstore: bool, pub qresync: Option, } @@ -40,7 +40,7 @@ pub struct Response { pub is_rev2: bool, pub closed_previous: bool, pub highest_modseq: Option, - pub mailbox_id: CompactString, + pub mailbox_id: String, } #[derive(Debug, Clone)] diff --git a/crates/imap-proto/src/protocol/status.rs b/crates/imap-proto/src/protocol/status.rs index 259618b4..106082e1 100644 --- a/crates/imap-proto/src/protocol/status.rs +++ b/crates/imap-proto/src/protocol/status.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use crate::utf7::utf7_encode; @@ -12,8 +12,8 @@ use super::quoted_string; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, pub items: Vec, } @@ -33,14 +33,14 @@ pub enum Status { #[derive(Debug, Clone, PartialEq, Eq)] pub struct StatusItem { - pub mailbox_name: CompactString, + pub mailbox_name: String, pub items: Vec<(Status, StatusItemType)>, } #[derive(Debug, Clone, PartialEq, Eq)] pub enum StatusItemType { Number(u64), - String(CompactString), + String(String), } impl StatusItem { diff --git a/crates/imap-proto/src/protocol/store.rs b/crates/imap-proto/src/protocol/store.rs index c636b41b..c59dc789 100644 --- a/crates/imap-proto/src/protocol/store.rs +++ b/crates/imap-proto/src/protocol/store.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::{Flag, ImapResponse, Sequence, fetch::FetchItem}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub sequence_set: Sequence, pub operation: Operation, pub is_silent: bool, diff --git a/crates/imap-proto/src/protocol/subscribe.rs b/crates/imap-proto/src/protocol/subscribe.rs index e6a78de5..1df766da 100644 --- a/crates/imap-proto/src/protocol/subscribe.rs +++ b/crates/imap-proto/src/protocol/subscribe.rs @@ -4,10 +4,10 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, - pub mailbox_name: CompactString, + pub tag: String, + pub mailbox_name: String, } diff --git a/crates/imap-proto/src/protocol/thread.rs b/crates/imap-proto/src/protocol/thread.rs index eede8b59..2c6a1768 100644 --- a/crates/imap-proto/src/protocol/thread.rs +++ b/crates/imap-proto/src/protocol/thread.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; + use super::{ImapResponse, search::Filter}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Arguments { - pub tag: CompactString, + pub tag: String, pub filter: Vec, pub algorithm: Algorithm, } diff --git a/crates/imap-proto/src/receiver.rs b/crates/imap-proto/src/receiver.rs index b2662bae..37d96736 100644 --- a/crates/imap-proto/src/receiver.rs +++ b/crates/imap-proto/src/receiver.rs @@ -4,7 +4,9 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; +use std::fmt::Display; + +use compact_str::{CompactString, format_compact}; use super::{ResponseCode, ResponseType}; @@ -17,7 +19,7 @@ pub enum Error { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Request { - pub tag: CompactString, + pub tag: String, pub command: T, pub tokens: Vec, } @@ -43,7 +45,7 @@ pub enum Token { impl Default for Request { fn default() -> Self { Self { - tag: CompactString::new(""), + tag: String::new(), command: T::default(), tokens: Vec::new(), } @@ -112,7 +114,7 @@ impl Receiver { if !self.buf.is_empty() { self.current_request_size += self.buf.len(); if self.current_request_size > self.max_request_size { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Request exceeds maximum limit of {} bytes.", self.max_request_size ))); @@ -128,7 +130,7 @@ impl Receiver { fn push_token(&mut self, token: Token) -> Result<(), Error> { self.current_request_size += 1; if self.current_request_size > self.max_request_size { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Request exceeds maximum limit of {} bytes.", self.max_request_size ))); @@ -150,7 +152,7 @@ impl Receiver { State::Tag => match ch { b' ' => { if !self.buf.is_empty() { - self.request.tag = CompactString::from_utf8(std::mem::replace( + self.request.tag = String::from_utf8(std::mem::replace( &mut self.buf, Vec::with_capacity(10), )) @@ -160,7 +162,7 @@ impl Receiver { } b'\t' | b'\r' => {} b'\n' => { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Missing command after tag {:?}, found CRLF instead.", std::str::from_utf8(&self.buf).unwrap_or_default() ))); @@ -187,7 +189,7 @@ impl Receiver { T::parse(&self.buf, is_uid).ok_or_else(|| { let command = String::from_utf8_lossy(&self.buf).into_owned(); - self.error_reset(format!( + self.error_reset(format_compact!( "Unrecognized command '{}'.", command )) @@ -206,7 +208,7 @@ impl Receiver { } } } else { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Invalid character {:?} in command name.", ch as char ))); @@ -315,7 +317,7 @@ impl Receiver { })?; if self.current_request_size + size as usize > self.max_request_size { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Literal exceeds the maximum request size of {} bytes.", self.max_request_size ))); @@ -343,7 +345,7 @@ impl Receiver { } } _ => { - return Err(self.error_reset(format!( + return Err(self.error_reset(format_compact!( "Invalid character {:?} in literal.", ch as char ))); @@ -386,10 +388,10 @@ impl Receiver { } impl Token { - pub fn unwrap_string(self) -> crate::parser::Result { + pub fn unwrap_string(self) -> crate::parser::Result { match self { Token::Argument(value) => { - CompactString::from_utf8(value).map_err(|_| "Invalid UTF-8 in argument.".into()) + String::from_utf8(value).map_err(|_| "Invalid UTF-8 in argument.".into()) } other => Ok(other.to_string()), } @@ -445,6 +447,12 @@ impl Token { } } +impl Display for Token { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(&String::from_utf8_lossy(self.as_bytes())) + } +} + impl Token { pub fn as_bytes(&self) -> &[u8] { match self { @@ -459,17 +467,14 @@ impl Token { Token::Nil => b"", } } - pub fn to_string(&self) -> CompactString { - CompactString::from_utf8_lossy(self.as_bytes()) - } } impl Error { - pub fn err(tag: Option, message: impl Into) -> Self { + pub fn err(tag: Option>, message: impl Into) -> Self { Error::Error { response: trc::ImapEvent::Error .ctx(trc::Key::Details, message) - .ctx_opt(trc::Key::Id, tag) + .ctx_opt(trc::Key::Id, tag.map(Into::into)) .ctx(trc::Key::Type, ResponseType::Bad) .code(ResponseCode::Parse), } @@ -493,13 +498,13 @@ impl Request { pub fn into_error(self, message: impl Into) -> trc::Error { trc::ImapEvent::Error .ctx(trc::Key::Details, message) - .ctx(trc::Key::Id, self.tag) + .ctx(trc::Key::Id, CompactString::from_string_buffer(self.tag)) } pub fn into_parse_error(self, message: impl Into) -> trc::Error { trc::ImapEvent::Error .ctx(trc::Key::Details, message) - .ctx(trc::Key::Id, self.tag) + .ctx(trc::Key::Id, CompactString::from_string_buffer(self.tag)) .ctx(trc::Key::Code, ResponseCode::Parse) .ctx(trc::Key::Type, ResponseType::Bad) } diff --git a/crates/imap-proto/src/utf7.rs b/crates/imap-proto/src/utf7.rs index 6298843f..4af7cdfa 100644 --- a/crates/imap-proto/src/utf7.rs +++ b/crates/imap-proto/src/utf7.rs @@ -7,8 +7,6 @@ // Ported from https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Imap/ImapEncoding.cs // Author: Jeffrey Stedfast -use compact_str::CompactString; - use crate::protocol::ProtocolVersion; static UTF_7_RANK: &[u8] = &[ @@ -22,7 +20,7 @@ static UTF_7_RANK: &[u8] = &[ static UTF_7_MAP: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; -pub fn utf7_decode(text: &str) -> Option { +pub fn utf7_decode(text: &str) -> Option { let mut bytes: Vec = Vec::with_capacity(text.len()); let mut bits = 0; let mut v: u32 = 0; @@ -70,11 +68,11 @@ pub fn utf7_decode(text: &str) -> Option { } } - CompactString::from_utf16(&bytes).ok() + String::from_utf16(&bytes).ok() } -pub fn utf7_encode(text: &str) -> CompactString { - let mut result = CompactString::with_capacity(text.len()); +pub fn utf7_encode(text: &str) -> String { + let mut result = String::with_capacity(text.len()); let mut shifted = false; let mut bits = 0; let mut u: u32 = 0; @@ -124,7 +122,7 @@ pub fn utf7_encode(text: &str) -> CompactString { } #[inline(always)] -pub fn utf7_maybe_decode(text: CompactString, version: ProtocolVersion) -> CompactString { +pub fn utf7_maybe_decode(text: String, version: ProtocolVersion) -> String { if version.is_rev2() { text } else { diff --git a/crates/imap/src/core/mailbox.rs b/crates/imap/src/core/mailbox.rs index 0e52aafe..e1ca972d 100644 --- a/crates/imap/src/core/mailbox.rs +++ b/crates/imap/src/core/mailbox.rs @@ -13,7 +13,7 @@ use common::{ listener::{SessionStream, limiter::InFlight}, sharing::EffectiveAcl, }; -use compact_str::CompactString; + use directory::backend::internal::manage::ManageDirectory; use email::{ mailbox::{ @@ -60,7 +60,7 @@ impl SessionData { // Fetch shared mailboxes for &account_id in access_token.shared_accounts(Collection::Mailbox) { - let prefix: CompactString = format!( + let prefix: String = format!( "{}/{}", session.server.core.jmap.shared_folder, session @@ -69,9 +69,8 @@ impl SessionData { .get_principal_name(account_id) .await .caused_by(trc::location!())? - .unwrap_or_else(|| Id::from(account_id).to_string().into()) - ) - .into(); + .unwrap_or_else(|| Id::from(account_id).to_string()) + ); mailboxes.push( session .fetch_account_mailboxes(account_id, prefix.into(), &access_token, None) @@ -89,7 +88,7 @@ impl SessionData { async fn fetch_account_mailboxes( &self, account_id: u32, - mailbox_prefix: Option, + mailbox_prefix: Option, access_token: &AccessToken, current_state: Option, ) -> trc::Result> { @@ -153,7 +152,7 @@ impl SessionData { // Build mailbox path and map it to its effective id let mailbox_name = if let Some(prefix) = &account.prefix { - let mut name = CompactString::with_capacity(prefix.len() + mailbox.path.len() + 1); + let mut name = String::with_capacity(prefix.len() + mailbox.path.len() + 1); name.push_str(prefix.as_str()); name.push('/'); name.push_str(mailbox.path.as_str()); @@ -167,7 +166,7 @@ impl SessionData { .jmap .default_folders .iter() - .find(|f| f.name == mailbox_name || f.aliases.iter().any(|a| a == mailbox_name)) + .find(|f| f.name == mailbox_name || f.aliases.iter().any(|a| a == &mailbox_name)) .and_then(|f| special_uses.get(&f.special_use)) .copied() .unwrap_or(mailbox.document_id); @@ -275,7 +274,7 @@ impl SessionData { // Fetch mailboxes for each new shared account for account_id in added_account_ids { - let prefix: CompactString = format!( + let prefix: String = format!( "{}/{}", self.server.core.jmap.shared_folder, self.server @@ -283,9 +282,8 @@ impl SessionData { .get_principal_name(account_id) .await .caused_by(trc::location!())? - .unwrap_or_else(|| Id::from(account_id).to_string().into()) - ) - .into(); + .unwrap_or_else(|| Id::from(account_id).to_string()) + ); added_accounts.push( self.fetch_account_mailboxes(account_id, prefix.into(), &access_token, None) .await? diff --git a/crates/imap/src/core/mod.rs b/crates/imap/src/core/mod.rs index 4e234fc8..cc816119 100644 --- a/crates/imap/src/core/mod.rs +++ b/crates/imap/src/core/mod.rs @@ -16,7 +16,7 @@ use common::{ auth::AccessToken, listener::{ServerInstance, SessionStream, limiter::InFlight}, }; -use compact_str::CompactString; + use imap_proto::{ Command, protocol::{ProtocolVersion, list::Attribute}, @@ -94,8 +94,8 @@ pub struct MailboxId { #[derive(Debug, Clone, Default)] pub struct Account { pub account_id: u32, - pub prefix: Option, - pub mailbox_names: BTreeMap, + pub prefix: Option, + pub mailbox_names: BTreeMap, pub mailbox_state: AHashMap, pub state: AccountState, } @@ -144,9 +144,9 @@ pub struct ImapId { #[derive(Debug, Default)] pub struct MailboxSync { - pub added: Vec, - pub changed: Vec, - pub deleted: Vec, + pub added: Vec, + pub changed: Vec, + pub deleted: Vec, } pub enum SavedSearch { diff --git a/crates/imap/src/op/acl.rs b/crates/imap/src/op/acl.rs index 43fb71a8..af4e3d7d 100644 --- a/crates/imap/src/op/acl.rs +++ b/crates/imap/src/op/acl.rs @@ -10,6 +10,7 @@ use common::{ auth::AccessToken, listener::SessionStream, sharing::EffectiveAcl, storage::index::ObjectIndexBuilder, }; + use compact_str::ToCompactString; use directory::{ Permission, QueryBy, Type, @@ -124,7 +125,7 @@ impl Session { .with_tag(arguments.tag) .serialize( GetAclResponse { - mailbox_name: arguments.mailbox_name, + mailbox_name: arguments.mailbox_name.to_string(), permissions, } .into_bytes(is_rev2), @@ -212,7 +213,7 @@ impl Session { .with_tag(arguments.tag) .serialize( MyRightsResponse { - mailbox_name: arguments.mailbox_name, + mailbox_name: arguments.mailbox_name.to_string(), rights, } .into_bytes(is_rev2), diff --git a/crates/imap/src/op/authenticate.rs b/crates/imap/src/op/authenticate.rs index 26f4f8e3..0e0248c3 100644 --- a/crates/imap/src/op/authenticate.rs +++ b/crates/imap/src/op/authenticate.rs @@ -11,7 +11,7 @@ use common::{ }, listener::{SessionStream, limiter::LimiterResult}, }; -use compact_str::CompactString; + use directory::Permission; use imap_proto::{ Command, ResponseCode, StatusResponse, @@ -74,7 +74,7 @@ impl Session { pub async fn authenticate( &mut self, credentials: Credentials, - tag: CompactString, + tag: String, ) -> trc::Result<()> { // Authenticate let access_token = self diff --git a/crates/imap/src/op/create.rs b/crates/imap/src/op/create.rs index 63112bed..bb96017b 100644 --- a/crates/imap/src/op/create.rs +++ b/crates/imap/src/op/create.rs @@ -14,7 +14,7 @@ use crate::{ use common::{ config::jmap::settings::SpecialUse, listener::SessionStream, storage::index::ObjectIndexBuilder, }; -use compact_str::CompactString; + use directory::Permission; use email::mailbox::cache::{MailboxCacheAccess, MessageMailboxCache}; use imap_proto::{ @@ -177,7 +177,7 @@ impl SessionData { } // Validate special folders - let full_path: CompactString = path.join("/").into(); + let full_path: String = path.join("/"); let mut parent_mailbox_id = None; let mut parent_mailbox_name = None; let (account_id, path) = { @@ -190,11 +190,7 @@ impl SessionData { .details("Mailboxes under root shared folders are not allowed.") .code(ResponseCode::Cannot)); } - let prefix = Some(CompactString::from(format!( - "{}/{}", - path.remove(0), - path.remove(0) - ))); + let prefix = Some(format!("{}/{}", path.remove(0), path.remove(0))); // Locate account if let Some(account) = mailboxes @@ -232,7 +228,7 @@ impl SessionData { if path.len() > 1 { let mut create_path = Vec::with_capacity(path.len()); while !path.is_empty() { - let mailbox_name: CompactString = path.join("/").into(); + let mailbox_name: String = path.join("/"); if let Some(&mailbox_id) = account.mailbox_names.get(&mailbox_name) { parent_mailbox_id = mailbox_id.into(); parent_mailbox_name = mailbox_name.into(); @@ -311,9 +307,9 @@ impl SessionData { pub struct CreateParams<'x> { pub account_id: u32, pub path: Vec<&'x str>, - pub full_path: CompactString, + pub full_path: String, pub parent_mailbox_id: Option, - pub parent_mailbox_name: Option, + pub parent_mailbox_name: Option, pub special_use: Option, pub is_rename: bool, } diff --git a/crates/imap/src/op/fetch.rs b/crates/imap/src/op/fetch.rs index 401a48df..9bd1ed15 100644 --- a/crates/imap/src/op/fetch.rs +++ b/crates/imap/src/op/fetch.rs @@ -495,14 +495,12 @@ impl SessionData { } Attribute::EmailId => { items.push(DataItem::EmailId { - email_id: Id::from_parts(account_id, id).to_string().into(), + email_id: Id::from_parts(account_id, id).to_string(), }); } Attribute::ThreadId => { items.push(DataItem::ThreadId { - thread_id: Id::from_parts(account_id, data.thread_id) - .to_string() - .into(), + thread_id: Id::from_parts(account_id, data.thread_id).to_string(), }); } } diff --git a/crates/imap/src/op/list.rs b/crates/imap/src/op/list.rs index 93ac6188..8208857e 100644 --- a/crates/imap/src/op/list.rs +++ b/crates/imap/src/op/list.rs @@ -11,7 +11,7 @@ use crate::{ spawn_op, }; use common::listener::SessionStream; -use compact_str::CompactString; + use directory::Permission; use imap_proto::{ Command, StatusResponse, @@ -163,7 +163,7 @@ impl SessionData { // Append reference name if !patterns.is_empty() && !reference_name.is_empty() { patterns.iter_mut().for_each(|item| { - *item = format!("{}{}", reference_name, item).into(); + *item = format!("{}{}", reference_name, item); }) } @@ -321,7 +321,7 @@ impl SessionData { } #[allow(clippy::while_let_on_iterator)] -pub fn matches_pattern(patterns: &[CompactString], mailbox_name: &str) -> bool { +pub fn matches_pattern(patterns: &[String], mailbox_name: &str) -> bool { if patterns.is_empty() { return true; } diff --git a/crates/imap/src/op/quota.rs b/crates/imap/src/op/quota.rs index 82605a7c..af2187b5 100644 --- a/crates/imap/src/op/quota.rs +++ b/crates/imap/src/op/quota.rs @@ -185,9 +185,9 @@ impl SessionData { // Build response let response = Response { - quota_root_items: vec![arguments.name, format!("#{account_id}").into()], + quota_root_items: vec![arguments.name, format!("#{account_id}")], quota_items: vec![QuotaItem { - name: format!("#{account_id}").into(), + name: format!("#{account_id}"), resources: vec![QuotaResource { resource: QuotaResourceName::Storage, total: access_token.quota, diff --git a/crates/imap/src/op/select.rs b/crates/imap/src/op/select.rs index 150cf498..9250c192 100644 --- a/crates/imap/src/op/select.rs +++ b/crates/imap/src/op/select.rs @@ -132,8 +132,7 @@ impl Session { is_rev2, highest_modseq, mailbox_id: Id::from_parts(mailbox.id.account_id, mailbox.id.mailbox_id) - .to_string() - .into(), + .to_string(), }; // Update state diff --git a/crates/imap/src/op/status.rs b/crates/imap/src/op/status.rs index 6cefb75b..f5969a10 100644 --- a/crates/imap/src/op/status.rs +++ b/crates/imap/src/op/status.rs @@ -12,7 +12,7 @@ use crate::{ spawn_op, }; use common::listener::SessionStream; -use compact_str::CompactString; + use directory::Permission; use email::message::cache::{MessageCacheAccess, MessageCacheFetch}; use imap_proto::{ @@ -90,11 +90,7 @@ impl Session { } impl SessionData { - pub async fn status( - &self, - mailbox_name: CompactString, - items: &[Status], - ) -> trc::Result { + pub async fn status(&self, mailbox_name: String, items: &[Status]) -> trc::Result { // Get mailbox id let mailbox = if let Some(mailbox) = self.get_mailbox_by_name(&mailbox_name) { mailbox @@ -200,8 +196,7 @@ impl SessionData { *item, StatusItemType::String( Id::from_parts(mailbox.account_id, mailbox.mailbox_id) - .to_string() - .into(), + .to_string(), ), )); } diff --git a/crates/imap/src/op/subscribe.rs b/crates/imap/src/op/subscribe.rs index cf3dc66c..b08ae2dd 100644 --- a/crates/imap/src/op/subscribe.rs +++ b/crates/imap/src/op/subscribe.rs @@ -11,7 +11,7 @@ use crate::{ spawn_op, }; use common::{listener::SessionStream, storage::index::ObjectIndexBuilder}; -use compact_str::CompactString; + use directory::Permission; use imap_proto::{Command, ResponseCode, StatusResponse, receiver::Request}; use jmap_proto::types::collection::Collection; @@ -50,8 +50,8 @@ impl Session { impl SessionData { pub async fn subscribe_folder( &self, - tag: CompactString, - mailbox_name: CompactString, + tag: String, + mailbox_name: String, subscribe: bool, op_start: Instant, ) -> trc::Result { diff --git a/crates/jmap-proto/src/method/changes.rs b/crates/jmap-proto/src/method/changes.rs index 82f8b740..e2b3b6cf 100644 --- a/crates/jmap-proto/src/method/changes.rs +++ b/crates/jmap-proto/src/method/changes.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::format_compact; + use crate::{ parser::{Ignore, JsonObjectParser, Token, json::Parser}, request::{RequestProperty, method::MethodObject}, @@ -69,7 +71,7 @@ impl JsonObjectParser for ChangesRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/changes", parser.ctx))); + .details(format_compact!("{}/changes", parser.ctx))); } }, account_id: Id::default(), diff --git a/crates/jmap-proto/src/method/copy.rs b/crates/jmap-proto/src/method/copy.rs index e18ab388..e1f1fd46 100644 --- a/crates/jmap-proto/src/method/copy.rs +++ b/crates/jmap-proto/src/method/copy.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::format_compact; use serde::Serialize; use utils::map::vec_map::VecMap; @@ -94,7 +95,7 @@ impl JsonObjectParser for CopyRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/copy", parser.ctx))); + .details(format_compact!("{}/copy", parser.ctx))); } }, account_id: Id::default(), diff --git a/crates/jmap-proto/src/method/get.rs b/crates/jmap-proto/src/method/get.rs index 79f16a63..466279fa 100644 --- a/crates/jmap-proto/src/method/get.rs +++ b/crates/jmap-proto/src/method/get.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::format_compact; + use crate::{ object::{blob, email}, parser::{JsonObjectParser, Token, json::Parser}, @@ -81,7 +83,7 @@ impl JsonObjectParser for GetRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/get", parser.ctx))); + .details(format_compact!("{}/get", parser.ctx))); } }, account_id: Id::default(), diff --git a/crates/jmap-proto/src/method/query.rs b/crates/jmap-proto/src/method/query.rs index b89a2228..8423b9a4 100644 --- a/crates/jmap-proto/src/method/query.rs +++ b/crates/jmap-proto/src/method/query.rs @@ -6,6 +6,7 @@ use std::fmt::Display; +use compact_str::format_compact; use store::fts::{FilterItem, FilterType, FtsFilter}; use crate::{ @@ -165,7 +166,7 @@ impl JsonObjectParser for QueryRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/query", parser.ctx))); + .details(format_compact!("{}/query", parser.ctx))); } }, filter: vec![], diff --git a/crates/jmap-proto/src/method/query_changes.rs b/crates/jmap-proto/src/method/query_changes.rs index 7f311e6f..cedf324b 100644 --- a/crates/jmap-proto/src/method/query_changes.rs +++ b/crates/jmap-proto/src/method/query_changes.rs @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::format_compact; + use crate::{ parser::{Ignore, JsonObjectParser, Token, json::Parser}, request::{RequestProperty, RequestPropertyParser, method::MethodObject}, @@ -72,7 +74,7 @@ impl JsonObjectParser for QueryChangesRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/queryChanges", parser.ctx))); + .details(format_compact!("{}/queryChanges", parser.ctx))); } }, filter: vec![], diff --git a/crates/jmap-proto/src/method/set.rs b/crates/jmap-proto/src/method/set.rs index 9f9cc450..6263fdc3 100644 --- a/crates/jmap-proto/src/method/set.rs +++ b/crates/jmap-proto/src/method/set.rs @@ -5,6 +5,7 @@ */ use ahash::AHashMap; +use compact_str::format_compact; use utils::map::{bitmap::Bitmap, vec_map::VecMap}; use crate::{ @@ -111,7 +112,7 @@ impl JsonObjectParser for SetRequest { _ => { return Err(trc::JmapEvent::UnknownMethod .into_err() - .details(format!("{}/set", parser.ctx))); + .details(format_compact!("{}/set", parser.ctx))); } }, account_id: Id::default(), diff --git a/crates/jmap-proto/src/parser/json.rs b/crates/jmap-proto/src/parser/json.rs index 207751a8..27af3004 100644 --- a/crates/jmap-proto/src/parser/json.rs +++ b/crates/jmap-proto/src/parser/json.rs @@ -6,6 +6,8 @@ use std::{fmt::Display, iter::Peekable, slice::Iter}; +use compact_str::format_compact; + use crate::request::method::MethodObject; use super::{Ignore, JsonObjectParser, Token}; @@ -43,18 +45,18 @@ impl<'x> Parser<'x> { pub fn error(&self, message: &str) -> trc::Error { trc::JmapEvent::NotJson .into_err() - .details(format!("{message} at position {}.", self.pos)) + .details(format_compact!("{message} at position {}.", self.pos)) } pub fn error_unterminated(&self) -> trc::Error { - trc::JmapEvent::NotJson.into_err().details(format!( + trc::JmapEvent::NotJson.into_err().details(format_compact!( "Unterminated string at position {pos}.", pos = self.pos )) } pub fn error_utf8(&self) -> trc::Error { - trc::JmapEvent::NotJson.into_err().details(format!( + trc::JmapEvent::NotJson.into_err().details(format_compact!( "Invalid UTF-8 sequence at position {pos}.", pos = self.pos )) @@ -62,11 +64,13 @@ impl<'x> Parser<'x> { pub fn error_value(&mut self) -> trc::Error { if self.is_eof || self.skip_string() { - trc::JmapEvent::InvalidArguments.into_err().details(format!( - "Invalid value {:?} at position {}.", - String::from_utf8_lossy(self.bytes[self.pos_marker..self.pos - 1].as_ref()), - self.pos - )) + trc::JmapEvent::InvalidArguments + .into_err() + .details(format_compact!( + "Invalid value {:?} at position {}.", + String::from_utf8_lossy(self.bytes[self.pos_marker..self.pos - 1].as_ref()), + self.pos + )) } else { self.error_unterminated() } diff --git a/crates/jmap-proto/src/parser/mod.rs b/crates/jmap-proto/src/parser/mod.rs index 7dbcde2a..da4a02e7 100644 --- a/crates/jmap-proto/src/parser/mod.rs +++ b/crates/jmap-proto/src/parser/mod.rs @@ -6,6 +6,8 @@ use std::fmt::Display; +use compact_str::format_compact; + use self::json::Parser; pub mod base32; @@ -117,18 +119,24 @@ impl Token { if self == token { Ok(()) } else { - Err(trc::JmapEvent::NotRequest.into_err().details(format!( - "Invalid JMAP request: expected '{token}', got '{self}'." - ))) + Err(trc::JmapEvent::NotRequest + .into_err() + .details(format_compact!( + "Invalid JMAP request: expected '{token}', got '{self}'." + ))) } } pub fn error(&self, property: &str, expected: &str) -> trc::Error { - trc::JmapEvent::InvalidArguments.into_err().details(if !property.is_empty() { - format!("Invalid argument for '{property:?}': expected '{expected}', got '{self}'.",) - } else { - format!("Invalid argument: expected '{expected}', got '{self}'.") - }) + trc::JmapEvent::InvalidArguments + .into_err() + .details(if !property.is_empty() { + format_compact!( + "Invalid argument for '{property:?}': expected '{expected}', got '{self}'.", + ) + } else { + format_compact!("Invalid argument: expected '{expected}', got '{self}'.") + }) } } diff --git a/crates/jmap-proto/src/request/capability.rs b/crates/jmap-proto/src/request/capability.rs index 8a7ff660..2603d172 100644 --- a/crates/jmap-proto/src/request/capability.rs +++ b/crates/jmap-proto/src/request/capability.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::CompactString; use utils::map::vec_map::VecMap; use crate::{ @@ -351,10 +352,11 @@ impl JsonObjectParser for Capability { impl Parser<'_> { fn error_capability(&mut self) -> trc::Error { if self.is_eof || self.skip_string() { - trc::JmapEvent::UnknownCapability.into_err().details( - String::from_utf8_lossy(self.bytes[self.pos_marker..self.pos - 1].as_ref()) - .into_owned(), - ) + trc::JmapEvent::UnknownCapability + .into_err() + .details(CompactString::from_utf8_lossy( + self.bytes[self.pos_marker..self.pos - 1].as_ref(), + )) } else { self.error_unterminated() } diff --git a/crates/jmap-proto/src/request/parser.rs b/crates/jmap-proto/src/request/parser.rs index c330b08c..fd89c8b3 100644 --- a/crates/jmap-proto/src/request/parser.rs +++ b/crates/jmap-proto/src/request/parser.rs @@ -6,6 +6,8 @@ use std::collections::HashMap; +use compact_str::ToCompactString; + use crate::{ method::{ changes::ChangesRequest, @@ -177,7 +179,7 @@ impl Request { } _ => Err(trc::JmapEvent::UnknownMethod .into_err() - .details(method_name.to_string())), + .details(method_name.to_compact_string())), }; let method = match method { diff --git a/crates/jmap-proto/src/response/references.rs b/crates/jmap-proto/src/response/references.rs index 2d6ac88e..065e2e94 100644 --- a/crates/jmap-proto/src/response/references.rs +++ b/crates/jmap-proto/src/response/references.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; +use compact_str::format_compact; use utils::map::vec_map::VecMap; use crate::{ @@ -51,7 +52,7 @@ impl Response { } else { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!( + .details(format_compact!( "Id reference {reference:?} does not exist." ))); } @@ -152,7 +153,7 @@ impl Response { Some(_) => { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!( + .details(format_compact!( "Id reference {parent_id:?} points to invalid type." ))); } @@ -255,7 +256,7 @@ impl Response { } else { Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Id reference {ir:?} not found."))) + .details(format_compact!("Id reference {ir:?} not found."))) } } @@ -277,7 +278,7 @@ impl Response { } else { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Id reference {parent_id:?} not found."))); + .details(format_compact!("Id reference {parent_id:?} not found."))); } } SetValue::IdReferences(id_refs) => { @@ -293,7 +294,9 @@ impl Response { } else { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Id reference {parent_id:?} not found."))); + .details(format_compact!( + "Id reference {parent_id:?} not found." + ))); } } } @@ -318,11 +321,11 @@ fn topological_sort( for (from_id, to_ids) in graph.iter() { for to_id in to_ids { if !create.contains_key(to_id) { - return Err(trc::JmapEvent::InvalidResultReference - .into_err() - .details(format!( + return Err(trc::JmapEvent::InvalidResultReference.into_err().details( + format_compact!( "Invalid reference to non-existing object {to_id:?} from {from_id:?}" - ))); + ), + )); } } } @@ -339,7 +342,7 @@ fn topological_sort( if it_stack.len() > 1000 { return Err(trc::JmapEvent::InvalidArguments .into_err() - .details("Cyclical references are not allowed.".to_string())); + .details("Cyclical references are not allowed.")); } it = to_ids.iter(); continue; @@ -455,7 +458,7 @@ impl EvalResult { _ => { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!( + .details(format_compact!( "Failed to evaluate {rr} result reference." ))); } @@ -463,9 +466,9 @@ impl EvalResult { } } _ => { - return Err(trc::JmapEvent::InvalidResultReference - .into_err() - .details(format!("Failed to evaluate {rr} result reference."))); + return Err(trc::JmapEvent::InvalidResultReference.into_err().details( + format_compact!("Failed to evaluate {rr} result reference."), + )); } } } @@ -473,7 +476,7 @@ impl EvalResult { } else { Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Failed to evaluate {rr} result reference."))) + .details(format_compact!("Failed to evaluate {rr} result reference."))) } } @@ -497,7 +500,7 @@ impl EvalResult { _ => { return Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!( + .details(format_compact!( "Failed to evaluate {rr} result reference." ))); } @@ -505,9 +508,9 @@ impl EvalResult { } } _ => { - return Err(trc::JmapEvent::InvalidResultReference - .into_err() - .details(format!("Failed to evaluate {rr} result reference."))); + return Err(trc::JmapEvent::InvalidResultReference.into_err().details( + format_compact!("Failed to evaluate {rr} result reference."), + )); } } } @@ -515,7 +518,7 @@ impl EvalResult { } else { Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Failed to evaluate {rr} result reference."))) + .details(format_compact!("Failed to evaluate {rr} result reference."))) } } @@ -525,7 +528,7 @@ impl EvalResult { } else { Err(trc::JmapEvent::InvalidResultReference .into_err() - .details(format!("Failed to evaluate {rr} result reference."))) + .details(format_compact!("Failed to evaluate {rr} result reference."))) } } } diff --git a/crates/jmap-proto/src/types/keyword.rs b/crates/jmap-proto/src/types/keyword.rs index 68abb875..975d60a3 100644 --- a/crates/jmap-proto/src/types/keyword.rs +++ b/crates/jmap-proto/src/types/keyword.rs @@ -6,7 +6,6 @@ use std::fmt::Display; -use compact_str::CompactString; use store::{Serialize, write::TagValue}; use crate::parser::{JsonObjectParser, json::Parser}; @@ -65,7 +64,7 @@ pub enum Keyword { Forwarded, #[serde(rename(serialize = "$mdnsent"))] MdnSent, - Other(CompactString), + Other(String), } impl JsonObjectParser for Keyword { @@ -109,9 +108,9 @@ impl JsonObjectParser for Keyword { } if parser.is_eof || parser.skip_string() { - Ok(Keyword::Other(CompactString::from_utf8_lossy( - parser.bytes[pos..parser.pos - 1].as_ref(), - ))) + Ok(Keyword::Other( + String::from_utf8_lossy(parser.bytes[pos..parser.pos - 1].as_ref()).into_owned(), + )) } else { Err(parser.error_unterminated()) } @@ -155,7 +154,7 @@ impl> From for Keyword { } } - Keyword::Other(CompactString::from(value)) + Keyword::Other(String::from(value)) } } @@ -238,7 +237,7 @@ impl Keyword { } } - pub fn into_id(self) -> Result { + pub fn into_id(self) -> Result { match self { Keyword::Seen => Ok(SEEN as u32), Keyword::Draft => Ok(DRAFT as u32), diff --git a/crates/jmap/src/api/session.rs b/crates/jmap/src/api/session.rs index e632b57b..9e6114cd 100644 --- a/crates/jmap/src/api/session.rs +++ b/crates/jmap/src/api/session.rs @@ -59,7 +59,6 @@ impl SessionHandler for Server { .get_principal_name(*id) .await .caused_by(trc::location!())? - .map(Into::into) .unwrap_or_else(|| Id::from(*id).to_string()), is_personal, is_readonly, diff --git a/crates/jmap/src/identity/get.rs b/crates/jmap/src/identity/get.rs index 0b9503f4..ada3c658 100644 --- a/crates/jmap/src/identity/get.rs +++ b/crates/jmap/src/identity/get.rs @@ -5,7 +5,6 @@ */ use common::{Server, storage::index::ObjectIndexBuilder}; -use compact_str::format_compact; use directory::QueryBy; use email::identity::{ArchivedEmailAddress, Identity}; use jmap_proto::{ @@ -182,7 +181,7 @@ impl IdentityGet for Server { let name = if name.is_empty() { email.clone() } else if has_many { - format_compact!("{} <{}>", name, email) + format!("{} <{}>", name, email) } else { name.clone() }; diff --git a/crates/jmap/src/identity/set.rs b/crates/jmap/src/identity/set.rs index 4bf11ba0..bca47765 100644 --- a/crates/jmap/src/identity/set.rs +++ b/crates/jmap/src/identity/set.rs @@ -63,7 +63,7 @@ impl IdentitySet for Server { .directory() .query(QueryBy::Id(account_id), false) .await? - .is_none_or(|p| !p.emails.iter().any(|e| e == identity.email)) + .is_none_or(|p| !p.emails.iter().any(|e| e == &identity.email)) { response.not_created.append( id, @@ -189,7 +189,7 @@ fn validate_identity_value( ) -> Result<(), SetError> { match (property, value) { (Property::Name, MaybePatchValue::Value(Value::Text(value))) if value.len() < 255 => { - identity.name = value.into(); + identity.name = value; } (Property::Email, MaybePatchValue::Value(Value::Text(value))) if is_create && value.len() < 255 => @@ -203,12 +203,12 @@ fn validate_identity_value( (Property::TextSignature, MaybePatchValue::Value(Value::Text(value))) if value.len() < 2048 => { - identity.text_signature = value.into(); + identity.text_signature = value; } (Property::HtmlSignature, MaybePatchValue::Value(Value::Text(value))) if value.len() < 2048 => { - identity.html_signature = value.into(); + identity.html_signature = value; } (Property::ReplyTo | Property::Bcc, MaybePatchValue::Value(Value::List(value))) => { let mut addresses = Vec::with_capacity(value.len()); @@ -223,10 +223,10 @@ fn validate_identity_value( match (key, value) { (Property::Email, Value::Text(value)) if value.len() < 255 => { is_valid = true; - address.email = value.into(); + address.email = value; } (Property::Name, Value::Text(value)) if value.len() < 255 => { - address.name = Some(value.into()); + address.name = Some(value); } (Property::Name, Value::Null) => (), _ => { diff --git a/crates/jmap/src/push/set.rs b/crates/jmap/src/push/set.rs index 30f41a13..51505a99 100644 --- a/crates/jmap/src/push/set.rs +++ b/crates/jmap/src/push/set.rs @@ -6,7 +6,7 @@ use base64::{Engine, engine::general_purpose}; use common::{Server, auth::AccessToken}; -use compact_str::CompactString; + use email::push::{Keys, PushSubscription}; use jmap_proto::{ error::set::SetError, @@ -101,7 +101,7 @@ impl PushSubscriptionSet for Server { .sample_iter(Alphanumeric) .take(VERIFICATION_CODE_LEN) .map(char::from) - .collect::(); + .collect::(); // Insert record let document_id = self @@ -218,12 +218,12 @@ fn validate_push_value( (Property::DeviceClientId, MaybePatchValue::Value(Value::Text(value))) if is_create && value.len() < 255 => { - push.device_client_id = value.into(); + push.device_client_id = value; } (Property::Url, MaybePatchValue::Value(Value::Text(value))) if is_create && value.len() < 512 && value.starts_with("https://") => { - push.url = value.into(); + push.url = value; } (Property::Keys, MaybePatchValue::Value(Value::Object(value))) if is_create && value.0.len() == 2 => diff --git a/crates/jmap/src/sieve/set.rs b/crates/jmap/src/sieve/set.rs index a350a4f9..0927422c 100644 --- a/crates/jmap/src/sieve/set.rs +++ b/crates/jmap/src/sieve/set.rs @@ -9,7 +9,7 @@ use common::{ auth::{AccessToken, ResourceToken}, storage::index::ObjectIndexBuilder, }; -use compact_str::CompactString; + use email::sieve::{ ArchivedSieveScript, SieveScript, activate::SieveScriptActivate, delete::SieveScriptDelete, }; @@ -401,7 +401,7 @@ impl SieveScriptSet for Server { } } - changes.name = value.into(); + changes.name = value; } (Property::BlobId, MaybePatchValue::Value(Value::BlobId(value))) => { blob_id = value.into(); @@ -425,7 +425,7 @@ impl SieveScriptSet for Server { .sample_iter(Alphanumeric) .take(15) .map(char::from) - .collect::(); + .collect::(); } // Set script as inactive diff --git a/crates/jmap/src/submission/set.rs b/crates/jmap/src/submission/set.rs index da655a00..13dd3d58 100644 --- a/crates/jmap/src/submission/set.rs +++ b/crates/jmap/src/submission/set.rs @@ -11,7 +11,7 @@ use common::{ listener::{ServerInstance, stream::NullIo}, storage::index::ObjectIndexBuilder, }; -use compact_str::CompactString; + use email::{ identity::Identity, message::metadata::{ArchivedHeaderName, ArchivedHeaderValue, MessageMetadata}, @@ -39,7 +39,7 @@ use smtp::{ core::{Session, SessionData}, queue::spool::SmtpSpool, }; -use smtp_proto::{MailFrom, Mtrk, RcptTo, request::parser::Rfc5321Parser}; +use smtp_proto::{MailFrom, RcptTo, request::parser::Rfc5321Parser}; use store::write::{BatchBuilder, now}; use trc::AddContext; use utils::{BlobHash, map::vec_map::VecMap, sanitize_email}; @@ -317,8 +317,8 @@ impl EmailSubmissionSet for Server { thread_id: u32::MAX, ..Default::default() }; - let mut mail_from = None; - let mut rcpt_to: Vec> = Vec::new(); + let mut mail_from: Option> = None; + let mut rcpt_to: Vec> = Vec::new(); for (property, value) in object.0 { let value = match response.eval_object_references(value) { @@ -354,24 +354,7 @@ impl EmailSubmissionSet for Server { email: addr.address.clone(), parameters: params, }; - mail_from = MailFrom { - address: CompactString::from(addr.address), - flags: addr.flags, - size: addr.size, - trans_id: addr.trans_id.map(Into::into), - by: addr.by, - env_id: addr.env_id.map(Into::into), - solicit: addr.solicit.map(Into::into), - mtrk: addr.mtrk.map(|m| Mtrk { - certifier: m.certifier.into(), - timeout: m.timeout, - }), - auth: addr.auth.map(Into::into), - hold_for: addr.hold_for, - hold_until: addr.hold_until, - mt_priority: addr.mt_priority, - } - .into(); + mail_from = addr.into(); } Err(err) => { return Ok(Err(SetError::invalid_properties() @@ -407,14 +390,7 @@ impl EmailSubmissionSet for Server { email: addr.address.clone(), parameters: params, }); - rcpt_to.push(RcptTo { - address: CompactString::new( - addr.address, - ), - orcpt: addr.orcpt.map(Into::into), - rrvs: addr.rrvs, - flags: addr.flags, - }); + rcpt_to.push(addr); } } Err(err) => { @@ -494,7 +470,7 @@ impl EmailSubmissionSet for Server { parameters: None, }; MailFrom { - address: CompactString::new(identity_mail_from.as_str()), + address: identity_mail_from, ..Default::default() } }; @@ -539,7 +515,7 @@ impl EmailSubmissionSet for Server { parameters: None, }); rcpt_to.push(RcptTo { - address: CompactString::new(address.as_str()), + address, ..Default::default() }); } diff --git a/crates/jmap/src/vacation/set.rs b/crates/jmap/src/vacation/set.rs index ce6b3547..91064522 100644 --- a/crates/jmap/src/vacation/set.rs +++ b/crates/jmap/src/vacation/set.rs @@ -174,19 +174,19 @@ impl VacationResponseSet for Server { if value.len() < 512 => { build_script = true; - vacation.subject = Some(value.into()); + vacation.subject = Some(value); } (Property::HtmlBody, MaybePatchValue::Value(Value::Text(value))) if value.len() < 2048 => { build_script = true; - vacation.html_body = Some(value.into()); + vacation.html_body = Some(value); } (Property::TextBody, MaybePatchValue::Value(Value::Text(value))) if value.len() < 2048 => { build_script = true; - vacation.text_body = Some(value.into()); + vacation.text_body = Some(value); } (Property::FromDate, MaybePatchValue::Value(Value::Date(date))) => { vacation.from_date = Some(date.timestamp() as u64); diff --git a/crates/managesieve/src/core/mod.rs b/crates/managesieve/src/core/mod.rs index 35f02d6d..bfaa46f2 100644 --- a/crates/managesieve/src/core/mod.rs +++ b/crates/managesieve/src/core/mod.rs @@ -14,6 +14,7 @@ use common::{ auth::AccessToken, listener::{ServerInstance, limiter::InFlight}, }; + use compact_str::CompactString; use imap_proto::receiver::{CommandParser, Receiver}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -132,7 +133,7 @@ pub enum ResponseCode { Active, NonExistent, AlreadyExists, - Tag(CompactString), + Tag(String), Warnings, } diff --git a/crates/managesieve/src/op/authenticate.rs b/crates/managesieve/src/op/authenticate.rs index 8bf37fd6..b616d384 100644 --- a/crates/managesieve/src/op/authenticate.rs +++ b/crates/managesieve/src/op/authenticate.rs @@ -11,7 +11,7 @@ use common::{ }, listener::{SessionStream, limiter::LimiterResult}, }; -use compact_str::CompactString; + use directory::Permission; use imap_proto::{ protocol::authenticate::Mechanism, @@ -32,7 +32,7 @@ impl Session { let mut tokens = request.tokens.into_iter(); let mechanism = Mechanism::parse(&tokens.next().unwrap().unwrap_bytes()) .map_err(|err| trc::AuthEvent::Error.into_err().details(err))?; - let mut params: Vec = tokens + let mut params: Vec = tokens .filter_map(|token| token.unwrap_string().ok()) .collect(); diff --git a/crates/services/src/state_manager/http.rs b/crates/services/src/state_manager/http.rs index 7aa11b44..26f72f41 100644 --- a/crates/services/src/state_manager/http.rs +++ b/crates/services/src/state_manager/http.rs @@ -8,7 +8,7 @@ use std::time::{Duration, Instant}; use base64::Engine; use common::ipc::EncryptionKeys; -use compact_str::CompactString; + use jmap_proto::{response::status::StateChangeResponse, types::id::Id}; use reqwest::header::{CONTENT_ENCODING, CONTENT_TYPE}; use tokio::sync::mpsc; @@ -58,7 +58,7 @@ impl PushServer { } pub(crate) async fn http_request( - url: CompactString, + url: String, mut body: String, keys: Option, push_timeout: Duration, diff --git a/crates/services/src/state_manager/mod.rs b/crates/services/src/state_manager/mod.rs index 6e392c8d..3327ef0d 100644 --- a/crates/services/src/state_manager/mod.rs +++ b/crates/services/src/state_manager/mod.rs @@ -12,7 +12,7 @@ pub mod push; use std::time::{Duration, Instant}; use common::ipc::EncryptionKeys; -use compact_str::CompactString; + use jmap_proto::types::{id::Id, state::StateChange, type_state::DataType}; use tokio::sync::mpsc; use utils::map::bitmap::Bitmap; @@ -31,7 +31,7 @@ pub enum SubscriberType { #[derive(Debug)] pub struct PushServer { - url: CompactString, + url: String, keys: Option, num_attempts: u32, last_request: Instant, @@ -63,13 +63,13 @@ pub enum PushUpdate { Verify { id: u32, account_id: u32, - url: CompactString, - code: CompactString, + url: String, + code: String, keys: Option, }, Register { id: Id, - url: CompactString, + url: String, keys: Option, }, Unregister { diff --git a/crates/smtp/src/core/mod.rs b/crates/smtp/src/core/mod.rs index 8a47b772..96b39e47 100644 --- a/crates/smtp/src/core/mod.rs +++ b/crates/smtp/src/core/mod.rs @@ -17,7 +17,7 @@ use common::{ config::smtp::auth::VerifyStrategy, listener::{ServerInstance, asn::AsnGeoLookupResult}, }; -use compact_str::{CompactString, ToCompactString}; + use directory::Directory; use mail_auth::{IprevOutput, SpfOutput}; use smtp_proto::request::receiver::{ @@ -56,7 +56,7 @@ pub enum State { } pub struct Session { - pub hostname: CompactString, + pub hostname: String, pub state: State, pub instance: Arc, pub server: Server, @@ -68,13 +68,13 @@ pub struct Session { pub struct SessionData { pub session_id: u64, pub local_ip: IpAddr, - pub local_ip_str: CompactString, + pub local_ip_str: String, pub local_port: u16, pub remote_ip: IpAddr, - pub remote_ip_str: CompactString, + pub remote_ip_str: String, pub remote_port: u16, pub asn_geo_data: AsnGeoLookupResult, - pub helo_domain: CompactString, + pub helo_domain: String, pub mail_from: Option, pub rcpt_to: Vec, @@ -101,11 +101,11 @@ pub struct SessionData { #[derive(Clone, Debug)] pub struct SessionAddress { - pub address: CompactString, - pub address_lcase: CompactString, - pub domain: CompactString, + pub address: String, + pub address_lcase: String, + pub domain: String, pub flags: u64, - pub dsn_info: Option, + pub dsn_info: Option, } #[derive(Debug, Default)] @@ -152,11 +152,11 @@ impl SessionData { local_ip, local_port, remote_ip, - local_ip_str: local_ip.to_compact_string(), - remote_ip_str: remote_ip.to_compact_string(), + local_ip_str: local_ip.to_string(), + remote_ip_str: remote_ip.to_string(), remote_port, asn_geo_data, - helo_domain: CompactString::new(""), + helo_domain: String::new(), mail_from: None, rcpt_to: Vec::new(), authenticated_as: None, @@ -248,7 +248,7 @@ impl Session { } } - pub fn has_failed(&mut self) -> Option { + pub fn has_failed(&mut self) -> Option { if self.stream.tx_buf.first().is_none_or(|&c| c == b'2') { self.stream.tx_buf.clear(); None @@ -309,7 +309,7 @@ impl Default for SessionData { } impl SessionAddress { - pub fn new(address: CompactString) -> Self { + pub fn new(address: String) -> Self { let address_lcase = address.to_lowercase(); SessionAddress { domain: address_lcase.domain_part().into(), diff --git a/crates/smtp/src/core/params.rs b/crates/smtp/src/core/params.rs index 802947c8..47827cae 100644 --- a/crates/smtp/src/core/params.rs +++ b/crates/smtp/src/core/params.rs @@ -7,7 +7,6 @@ use std::time::Duration; use common::{config::smtp::auth::VerifyStrategy, listener::SessionStream}; -use compact_str::CompactString; use super::Session; @@ -75,7 +74,7 @@ impl Session { let ac = &self.server.core.smtp.session.auth; self.params.auth_directory = self .server - .eval_if::(&ac.directory, self, self.data.session_id) + .eval_if::(&ac.directory, self, self.data.session_id) .await .and_then(|name| self.server.get_directory(&name)) .cloned(); diff --git a/crates/smtp/src/inbound/auth.rs b/crates/smtp/src/inbound/auth.rs index bd5b4129..e11d3e13 100644 --- a/crates/smtp/src/inbound/auth.rs +++ b/crates/smtp/src/inbound/auth.rs @@ -13,7 +13,7 @@ use common::{ }, listener::SessionStream, }; -use compact_str::CompactString; + use directory::Permission; use mail_parser::decoders::base64::base64_decode; use mail_send::Credentials; @@ -225,7 +225,7 @@ impl Session { self.data.authenticated_as.is_some() } - pub fn authenticated_emails(&self) -> &[CompactString] { + pub fn authenticated_emails(&self) -> &[String] { self.data .authenticated_as .as_ref() diff --git a/crates/smtp/src/inbound/data.rs b/crates/smtp/src/inbound/data.rs index a9ed1387..33c808cc 100644 --- a/crates/smtp/src/inbound/data.rs +++ b/crates/smtp/src/inbound/data.rs @@ -18,7 +18,7 @@ use common::{ psl, scripts::ScriptModification, }; -use compact_str::CompactString; + use mail_auth::{ AuthenticatedMessage, AuthenticationResults, DkimResult, DmarcResult, ReceivedSpf, common::{headers::HeaderWriter, verify::VerifySignature}, @@ -170,7 +170,7 @@ impl Session { .unwrap_or(VerifyStrategy::Relaxed); let arc_sealer = self .server - .eval_if::(&ac.arc.seal, self, self.data.session_id) + .eval_if::(&ac.arc.seal, self, self.data.session_id) .await .and_then(|name| self.server.get_arc_sealer(&name, self.data.session_id)); let arc_output = if arc.verify() || arc_sealer.is_some() { @@ -497,7 +497,7 @@ impl Session { // Sieve filtering if let Some((script, script_id)) = self .server - .eval_if::(&dc.script, self, self.data.session_id) + .eval_if::(&dc.script, self, self.data.session_id) .await .and_then(|name| { self.server @@ -636,7 +636,7 @@ impl Session { let raw_message = edited_message.as_deref().unwrap_or(raw_message.as_slice()); for signer in self .server - .eval_if::, _>(&ac.dkim.sign, self, self.data.session_id) + .eval_if::, _>(&ac.dkim.sign, self, self.data.session_id) .await .unwrap_or_default() { diff --git a/crates/smtp/src/inbound/ehlo.rs b/crates/smtp/src/inbound/ehlo.rs index b4cd636e..8bf932b1 100644 --- a/crates/smtp/src/inbound/ehlo.rs +++ b/crates/smtp/src/inbound/ehlo.rs @@ -11,7 +11,7 @@ use common::{ config::smtp::session::{Mechanism, Stage}, listener::SessionStream, }; -use compact_str::CompactString; + use mail_auth::{ SpfResult, spf::verify::{HasValidLabels, SpfParameters}, @@ -22,7 +22,7 @@ use trc::SmtpEvent; impl Session { pub async fn handle_ehlo( &mut self, - domain: CompactString, + domain: String, is_extended: bool, ) -> Result<(), ()> { // Set EHLO domain @@ -91,7 +91,7 @@ impl Session { // Sieve filtering if let Some((script, script_id)) = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.ehlo.script, self, self.data.session_id, @@ -277,7 +277,7 @@ impl Session { // No soliciting if let Some(value) = self .server - .eval_if::(&ec.no_soliciting, self, self.data.session_id) + .eval_if::(&ec.no_soliciting, self, self.data.session_id) .await { response.capabilities |= EXT_NO_SOLICITING; diff --git a/crates/smtp/src/inbound/hooks/message.rs b/crates/smtp/src/inbound/hooks/message.rs index 130d94df..9c6d0fd6 100644 --- a/crates/smtp/src/inbound/hooks/message.rs +++ b/crates/smtp/src/inbound/hooks/message.rs @@ -12,7 +12,7 @@ use common::{ config::smtp::session::{MTAHook, Stage}, listener::SessionStream, }; -use compact_str::{CompactString, ToCompactString}; + use mail_auth::AuthenticatedMessage; use trc::MtaHookEvent; @@ -105,7 +105,7 @@ impl Session { Modification::ChangeHeader { index, name, - value: CompactString::new(""), + value: String::new(), } } }); @@ -184,7 +184,7 @@ impl Session { context: Context { stage: stage.into(), client: Client { - ip: self.data.remote_ip.to_compact_string(), + ip: self.data.remote_ip.to_string(), port: self.data.remote_port, ptr: self .data @@ -211,10 +211,10 @@ impl Session { server: Server { name: Some(DAEMON_NAME.into()), port: self.data.local_port, - ip: self.data.local_ip.to_compact_string().into(), + ip: self.data.local_ip.to_string().into(), }, queue: queue_id.map(|id| Queue { - id: format!("{:x}", id).into(), + id: format!("{:x}", id), }), protocol: Protocol { version: 1 }, }, @@ -239,13 +239,13 @@ impl Session { .iter() .map(|(k, v)| { ( - CompactString::from_utf8_lossy(k), - CompactString::from_utf8_lossy(v), + String::from_utf8_lossy(k).into_owned(), + String::from_utf8_lossy(v).into_owned(), ) }) .collect(), server_headers: vec![], - contents: CompactString::from_utf8_lossy(message.raw_body()), + contents: String::from_utf8_lossy(message.raw_body()).into_owned(), size: message.raw_message().len(), }), }; @@ -254,8 +254,8 @@ impl Session { } } -fn flatten_parameters(parameters: AHashMap>) -> CompactString { - let mut arguments = CompactString::new(""); +fn flatten_parameters(parameters: AHashMap>) -> String { + let mut arguments = String::new(); for (key, value) in parameters { if !arguments.is_empty() { arguments.push(' '); diff --git a/crates/smtp/src/inbound/hooks/mod.rs b/crates/smtp/src/inbound/hooks/mod.rs index 43e6b0d2..6434630e 100644 --- a/crates/smtp/src/inbound/hooks/mod.rs +++ b/crates/smtp/src/inbound/hooks/mod.rs @@ -8,7 +8,7 @@ pub mod client; pub mod message; use ahash::AHashMap; -use compact_str::CompactString; + use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -36,46 +36,46 @@ pub struct Context { #[derive(Serialize, Deserialize)] pub struct Sasl { - pub login: CompactString, + pub login: String, #[serde(skip_serializing_if = "Option::is_none")] - pub method: Option, + pub method: Option, } #[derive(Serialize, Deserialize)] pub struct Client { - pub ip: CompactString, + pub ip: String, pub port: u16, - pub ptr: Option, - pub helo: Option, + pub ptr: Option, + pub helo: Option, #[serde(rename = "activeConnections")] pub active_connections: u32, } #[derive(Serialize, Deserialize)] pub struct Tls { - pub version: CompactString, - pub cipher: CompactString, + pub version: String, + pub cipher: String, #[serde(rename = "cipherBits")] #[serde(skip_serializing_if = "Option::is_none")] pub bits: Option, #[serde(rename = "certIssuer")] #[serde(skip_serializing_if = "Option::is_none")] - pub issuer: Option, + pub issuer: Option, #[serde(rename = "certSubject")] #[serde(skip_serializing_if = "Option::is_none")] - pub subject: Option, + pub subject: Option, } #[derive(Serialize, Deserialize)] pub struct Server { - pub name: Option, + pub name: Option, pub port: u16, - pub ip: Option, + pub ip: Option, } #[derive(Serialize, Deserialize)] pub struct Queue { - pub id: CompactString, + pub id: String, } #[derive(Serialize, Deserialize)] @@ -101,9 +101,9 @@ pub enum Stage { #[derive(Serialize, Deserialize)] pub struct Address { - pub address: CompactString, + pub address: String, #[serde(skip_serializing_if = "Option::is_none")] - pub parameters: Option>, + pub parameters: Option>, } #[derive(Serialize, Deserialize)] @@ -114,12 +114,12 @@ pub struct Envelope { #[derive(Serialize, Deserialize)] pub struct Message { - pub headers: Vec<(CompactString, CompactString)>, + pub headers: Vec<(String, String)>, #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(rename = "serverHeaders")] #[serde(default)] - pub server_headers: Vec<(CompactString, CompactString)>, - pub contents: CompactString, + pub server_headers: Vec<(String, String)>, + pub contents: String, pub size: usize, } @@ -149,9 +149,9 @@ pub struct SmtpResponse { #[serde(default)] pub status: Option, #[serde(default)] - pub enhanced_status: Option, + pub enhanced_status: Option, #[serde(default)] - pub message: Option, + pub message: Option, #[serde(default)] pub disconnect: bool, } @@ -161,39 +161,39 @@ pub struct SmtpResponse { pub enum Modification { #[serde(rename = "changeFrom")] ChangeFrom { - value: CompactString, + value: String, #[serde(default)] - parameters: AHashMap>, + parameters: AHashMap>, }, #[serde(rename = "addRecipient")] AddRecipient { - value: CompactString, + value: String, #[serde(default)] - parameters: AHashMap>, + parameters: AHashMap>, }, #[serde(rename = "deleteRecipient")] - DeleteRecipient { value: CompactString }, + DeleteRecipient { value: String }, #[serde(rename = "replaceContents")] - ReplaceContents { value: CompactString }, + ReplaceContents { value: String }, #[serde(rename = "addHeader")] AddHeader { - name: CompactString, - value: CompactString, + name: String, + value: String, }, #[serde(rename = "insertHeader")] InsertHeader { index: u32, - name: CompactString, - value: CompactString, + name: String, + value: String, }, #[serde(rename = "changeHeader")] ChangeHeader { index: u32, - name: CompactString, - value: CompactString, + name: String, + value: String, }, #[serde(rename = "deleteHeader")] - DeleteHeader { index: u32, name: CompactString }, + DeleteHeader { index: u32, name: String }, } impl From for Stage { diff --git a/crates/smtp/src/inbound/mail.rs b/crates/smtp/src/inbound/mail.rs index d61ede11..23dc6987 100644 --- a/crates/smtp/src/inbound/mail.rs +++ b/crates/smtp/src/inbound/mail.rs @@ -7,7 +7,7 @@ use std::time::{Duration, Instant, SystemTime}; use common::{config::smtp::session::Stage, listener::SessionStream, scripts::ScriptModification}; -use compact_str::CompactString; + use mail_auth::{IprevOutput, IprevResult, SpfOutput, SpfResult, spf::verify::SpfParameters}; use smtp_proto::{MAIL_BY_NOTIFY, MAIL_BY_RETURN, MAIL_REQUIRETLS, MailFrom, MtPriority}; use trc::SmtpEvent; @@ -20,7 +20,7 @@ use crate::{ }; impl Session { - pub async fn handle_mail_from(&mut self, from: MailFrom) -> Result<(), ()> { + pub async fn handle_mail_from(&mut self, from: MailFrom) -> Result<(), ()> { if self.data.helo_domain.is_empty() && (self.params.ehlo_require || self.params.spf_ehlo.verify() @@ -113,11 +113,7 @@ impl Session { let domain = address_lcase.domain_part().into(); (from.address, address_lcase, domain) } else { - ( - CompactString::new(""), - CompactString::new(""), - CompactString::new(""), - ) + (String::new(), String::new(), String::new()) }; let has_dsn = from.env_id.is_some(); @@ -155,7 +151,7 @@ impl Session { // Sieve filtering if let Some((script, script_id)) = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.mail.script, self, self.data.session_id, @@ -207,7 +203,7 @@ impl Session { // Address rewriting if let Some(new_address) = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.mail.rewrite, self, self.data.session_id, @@ -263,7 +259,7 @@ impl Session { .chain( self.authenticated_emails() .iter() - .map(|e| trc::Value::String(e.clone())) + .map(|e| trc::Value::String(e.as_str().into())) ) .collect::>() ); diff --git a/crates/smtp/src/inbound/milter/macros.rs b/crates/smtp/src/inbound/milter/macros.rs index 1e0dd506..565a7eca 100644 --- a/crates/smtp/src/inbound/milter/macros.rs +++ b/crates/smtp/src/inbound/milter/macros.rs @@ -6,8 +6,6 @@ use std::{borrow::Cow, net::IpAddr}; -use compact_str::CompactString; - use super::{Macro, Macros}; pub trait IntoMacroValue<'x> { @@ -161,7 +159,7 @@ impl<'x> IntoMacroValue<'x> for &'x str { } } -impl<'x> IntoMacroValue<'x> for &'x CompactString { +impl<'x> IntoMacroValue<'x> for &'x String { fn into_macro_value(self) -> Cow<'x, [u8]> { Cow::Borrowed(self.as_bytes()) } @@ -173,12 +171,6 @@ impl<'x> IntoMacroValue<'x> for String { } } -impl<'x> IntoMacroValue<'x> for &'x String { - fn into_macro_value(self) -> Cow<'x, [u8]> { - Cow::Borrowed(self.as_bytes()) - } -} - impl<'x> IntoMacroValue<'x> for Vec { fn into_macro_value(self) -> Cow<'x, [u8]> { Cow::Owned(self) diff --git a/crates/smtp/src/inbound/milter/message.rs b/crates/smtp/src/inbound/milter/message.rs index 56011c00..785dfe66 100644 --- a/crates/smtp/src/inbound/milter/message.rs +++ b/crates/smtp/src/inbound/milter/message.rs @@ -11,7 +11,7 @@ use common::{ config::smtp::session::{Milter, Stage}, listener::SessionStream, }; -use compact_str::CompactString; + use mail_auth::AuthenticatedMessage; use smtp_proto::{IntoString, request::parser::Rfc5321Parser}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -320,7 +320,7 @@ impl SessionData { { Ok(addr) => { mail_from.flags = addr.flags; - mail_from.dsn_info = addr.env_id.map(Into::into); + mail_from.dsn_info = addr.env_id; } Err(err) => { trc::event!( @@ -356,7 +356,7 @@ impl SessionData { { Ok(addr) => { rcpt.flags = addr.flags; - rcpt.dsn_info = addr.orcpt.map(Into::into); + rcpt.dsn_info = addr.orcpt; } Err(err) => { trc::event!( @@ -537,7 +537,7 @@ impl From for Rejection { } } -fn strip_brackets(addr: &str) -> CompactString { +fn strip_brackets(addr: &str) -> String { let addr = addr.trim(); if let Some(addr) = addr.strip_prefix('<') { if let Some((addr, _)) = addr.rsplit_once('>') { diff --git a/crates/smtp/src/inbound/milter/mod.rs b/crates/smtp/src/inbound/milter/mod.rs index 60934b51..023dbbfe 100644 --- a/crates/smtp/src/inbound/milter/mod.rs +++ b/crates/smtp/src/inbound/milter/mod.rs @@ -7,7 +7,7 @@ use std::{borrow::Cow, fmt::Display, net::IpAddr, sync::Arc, time::Duration}; use common::config::smtp::session::MilterVersion; -use compact_str::CompactString; + use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -30,7 +30,7 @@ pub struct MilterClient { options: u32, flags_actions: u32, flags_protocol: u32, - id: Arc, + id: Arc, session_id: u64, } @@ -104,7 +104,7 @@ pub enum Action { Discard, Reject, TempFail, - ReplyCode { code: [u8; 3], text: CompactString }, + ReplyCode { code: [u8; 3], text: String }, Shutdown, ConnectionFailure, } @@ -112,35 +112,35 @@ pub enum Action { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Modification { ChangeFrom { - sender: CompactString, - args: CompactString, + sender: String, + args: String, }, AddRcpt { - recipient: CompactString, - args: CompactString, + recipient: String, + args: String, }, DeleteRcpt { - recipient: CompactString, + recipient: String, }, ReplaceBody { value: Vec, }, AddHeader { - name: CompactString, - value: CompactString, + name: String, + value: String, }, InsertHeader { index: u32, - name: CompactString, - value: CompactString, + name: String, + value: String, }, ChangeHeader { index: u32, - name: CompactString, - value: CompactString, + name: String, + value: String, }, Quarantine { - reason: CompactString, + reason: String, }, } diff --git a/crates/smtp/src/inbound/milter/protocol.rs b/crates/smtp/src/inbound/milter/protocol.rs index 9ecf51df..906715b9 100644 --- a/crates/smtp/src/inbound/milter/protocol.rs +++ b/crates/smtp/src/inbound/milter/protocol.rs @@ -6,7 +6,7 @@ use std::net::IpAddr; -use compact_str::CompactString; + use crate::inbound::milter::Action; @@ -271,7 +271,7 @@ impl Response { match *bytes.next()? { SMFIR_ADDRCPT => Response::Modification(Modification::AddRcpt { recipient: read_nul_terminated(&mut bytes, frame_len)?, - args: CompactString::new(""), + args: String::new(), }), SMFIR_DELRCPT => Response::Modification(Modification::DeleteRcpt { recipient: read_nul_terminated(&mut bytes, frame_len)?, @@ -465,7 +465,7 @@ impl Response { fn read_nul_terminated( bytes: &mut std::slice::Iter, expected_len: usize, -) -> Option { +) -> Option { let mut buf = Vec::with_capacity(expected_len); loop { match bytes.next()? { @@ -473,7 +473,7 @@ fn read_nul_terminated( byte => buf.push(*byte), } } - CompactString::from_utf8(buf).ok() + String::from_utf8(buf).ok() } fn read_u32(bytes: &mut std::slice::Iter) -> Option { diff --git a/crates/smtp/src/inbound/rcpt.rs b/crates/smtp/src/inbound/rcpt.rs index 6efe86e6..3a154d39 100644 --- a/crates/smtp/src/inbound/rcpt.rs +++ b/crates/smtp/src/inbound/rcpt.rs @@ -7,7 +7,7 @@ use common::{ KV_GREYLIST, config::smtp::session::Stage, listener::SessionStream, scripts::ScriptModification, }; -use compact_str::{CompactString, format_compact}; + use directory::backend::RcptType; use smtp_proto::{ RCPT_NOTIFY_DELAY, RCPT_NOTIFY_FAILURE, RCPT_NOTIFY_NEVER, RCPT_NOTIFY_SUCCESS, RcptTo, @@ -22,7 +22,7 @@ use crate::{ }; impl Session { - pub async fn handle_rcpt_to(&mut self, to: RcptTo) -> Result<(), ()> { + pub async fn handle_rcpt_to(&mut self, to: RcptTo) -> Result<(), ()> { #[cfg(feature = "test_mode")] if self.instance.id.ends_with("-debug") { if to.address.contains("fail@") { @@ -91,7 +91,7 @@ impl Session { // Address rewriting and Sieve filtering let rcpt_script = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.rcpt.script, self, self.data.session_id, @@ -158,7 +158,7 @@ impl Session { // Address rewriting if let Some(new_address) = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.rcpt.rewrite, self, self.data.session_id, @@ -200,7 +200,7 @@ impl Session { let mut rcpt_members = None; if let Some(directory) = self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.rcpt.directory, self, self.data.session_id, @@ -394,7 +394,7 @@ impl Session { // Expand list if let Some(members) = rcpt_members { let list_addr = self.data.rcpt_to.pop().unwrap(); - let orcpt = format_compact!("rfc822;{}", list_addr.address_lcase); + let orcpt = format!("rfc822;{}", list_addr.address_lcase); for member in members { let mut member_addr = SessionAddress::new(member); if !self.data.rcpt_to.contains(&member_addr) @@ -411,7 +411,7 @@ impl Session { self.write(b"250 2.1.5 OK\r\n").await } - async fn rcpt_error(&mut self, response: &[u8], rcpt: CompactString) -> Result<(), ()> { + async fn rcpt_error(&mut self, response: &[u8], rcpt: String) -> Result<(), ()> { tokio::time::sleep(self.params.rcpt_errors_wait).await; self.data.rcpt_errors += 1; let has_too_many_errors = self.data.rcpt_errors >= self.params.rcpt_errors_max; diff --git a/crates/smtp/src/inbound/session.rs b/crates/smtp/src/inbound/session.rs index dcaa55e3..c384f88f 100644 --- a/crates/smtp/src/inbound/session.rs +++ b/crates/smtp/src/inbound/session.rs @@ -9,6 +9,7 @@ use common::{ expr::{self, functions::ResolveVariable, *}, listener::SessionStream, }; + use compact_str::ToCompactString; use smtp_proto::{ request::receiver::{ @@ -35,37 +36,14 @@ impl Session { match receiver.ingest(&mut iter, bytes) { Ok(request) => match request { Request::Rcpt { to } => { - self.handle_rcpt_to(RcptTo { - address: to.address.into(), - orcpt: to.orcpt.map(Into::into), - rrvs: to.rrvs, - flags: to.flags, - }) - .await?; + self.handle_rcpt_to(to).await?; } Request::Mail { from } => { - self.handle_mail_from(MailFrom { - address: from.address.into(), - flags: from.flags, - size: from.size, - trans_id: from.trans_id.map(Into::into), - by: from.by, - env_id: from.env_id.map(Into::into), - solicit: from.solicit.map(Into::into), - mtrk: from.mtrk.map(|m| Mtrk { - certifier: m.certifier.into(), - timeout: m.timeout, - }), - auth: from.auth.map(Into::into), - hold_for: from.hold_for, - hold_until: from.hold_until, - mt_priority: from.mt_priority, - }) - .await?; + self.handle_mail_from(from).await?; } Request::Ehlo { host } => { if self.instance.protocol == ServerProtocol::Smtp { - self.handle_ehlo(host.into(), true).await?; + self.handle_ehlo(host, true).await?; } else { trc::event!( Smtp(SmtpEvent::LhloExpected), @@ -220,7 +198,7 @@ impl Session { } Request::Helo { host } => { if self.instance.protocol == ServerProtocol::Smtp { - self.handle_ehlo(host.into(), false).await?; + self.handle_ehlo(host, false).await?; } else { trc::event!( Smtp(SmtpEvent::LhloExpected), @@ -233,7 +211,7 @@ impl Session { } Request::Lhlo { host } => { if self.instance.protocol == ServerProtocol::Lmtp { - self.handle_ehlo(host.into(), true).await?; + self.handle_ehlo(host, true).await?; } else { trc::event!( Smtp(SmtpEvent::EhloExpected), diff --git a/crates/smtp/src/inbound/spawn.rs b/crates/smtp/src/inbound/spawn.rs index 06a9db9b..2ffb0b7a 100644 --- a/crates/smtp/src/inbound/spawn.rs +++ b/crates/smtp/src/inbound/spawn.rs @@ -11,7 +11,7 @@ use common::{ core::BuildServer, listener::{self, SessionManager, SessionStream}, }; -use compact_str::CompactString; + use tokio_rustls::server::TlsStream; use trc::{SecurityEvent, SmtpEvent}; @@ -82,7 +82,7 @@ impl Session { // Sieve filtering if let Some((script, script_id)) = self .server - .eval_if::(&config.script, self, self.data.session_id) + .eval_if::(&config.script, self, self.data.session_id) .await .and_then(|name| { self.server @@ -118,7 +118,7 @@ impl Session { // Obtain hostname self.hostname = self .server - .eval_if::(&config.hostname, self, self.data.session_id) + .eval_if::(&config.hostname, self, self.data.session_id) .await .unwrap_or_default(); if self.hostname.is_empty() { @@ -132,7 +132,7 @@ impl Session { // Obtain greeting let greeting = self .server - .eval_if::(&config.greeting, self, self.data.session_id) + .eval_if::(&config.greeting, self, self.data.session_id) .await .filter(|g| !g.is_empty()) .map(|g| format!("220 {}\r\n", g)) diff --git a/crates/smtp/src/inbound/vrfy.rs b/crates/smtp/src/inbound/vrfy.rs index 6129a273..8e63946c 100644 --- a/crates/smtp/src/inbound/vrfy.rs +++ b/crates/smtp/src/inbound/vrfy.rs @@ -5,7 +5,7 @@ */ use common::listener::SessionStream; -use compact_str::CompactString; + use trc::SmtpEvent; use crate::core::Session; @@ -15,7 +15,7 @@ impl Session { pub async fn handle_vrfy(&mut self, address: String) -> Result<(), ()> { match self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.rcpt.directory, self, self.data.session_id, @@ -88,7 +88,7 @@ impl Session { pub async fn handle_expn(&mut self, address: String) -> Result<(), ()> { match self .server - .eval_if::( + .eval_if::( &self.server.core.smtp.session.rcpt.directory, self, self.data.session_id, diff --git a/crates/smtp/src/outbound/delivery.rs b/crates/smtp/src/outbound/delivery.rs index 4fddc5e9..79b244fd 100644 --- a/crates/smtp/src/outbound/delivery.rs +++ b/crates/smtp/src/outbound/delivery.rs @@ -20,7 +20,8 @@ use common::config::{ smtp::{queue::RequireOptional, report::AggregateFrequency}, }; use common::ipc::{PolicyType, QueueEvent, QueueEventStatus, TlsEvent}; -use compact_str::{CompactString, ToCompactString}; + +use compact_str::ToCompactString; use mail_auth::{ mta_sts::TlsRpt, report::tlsrpt::{FailureDetails, ResultType}, @@ -239,7 +240,7 @@ impl QueuedMessage { // Obtain next hop let (mut remote_hosts, is_smtp) = match server - .eval_if::(&queue_config.next_hop, &envelope, message.span_id) + .eval_if::(&queue_config.next_hop, &envelope, message.span_id) .await .and_then(|name| server.get_relay_host(&name, message.span_id)) { @@ -618,9 +619,10 @@ impl QueuedMessage { ); if strict { - last_status = Status::PermanentFailure(Error::MtaStsError( - format!("MX {:?} not authorized by policy.", envelope.mx).into(), - )); + last_status = Status::PermanentFailure(Error::MtaStsError(format!( + "MX {:?} not authorized by policy.", + envelope.mx + ))); continue 'next_host; } } else { @@ -930,11 +932,7 @@ impl QueuedMessage { // Obtain session parameters let local_hostname = server - .eval_if::( - &queue_config.hostname, - &envelope, - message.span_id, - ) + .eval_if::(&queue_config.hostname, &envelope, message.span_id) .await .filter(|s| !s.is_empty()) .unwrap_or_else(|| { diff --git a/crates/smtp/src/outbound/local.rs b/crates/smtp/src/outbound/local.rs index 11b51e26..1a604a45 100644 --- a/crates/smtp/src/outbound/local.rs +++ b/crates/smtp/src/outbound/local.rs @@ -71,7 +71,7 @@ impl Message { rcpt.status = Status::TemporaryFailure(HostResponse { hostname: ErrorDetails { entity: "localhost".into(), - details: format!("RCPT TO:<{}>", rcpt.address).into(), + details: format!("RCPT TO:<{}>", rcpt.address), }, response: Response { code: 451, @@ -85,7 +85,7 @@ impl Message { rcpt.status = Status::PermanentFailure(HostResponse { hostname: ErrorDetails { entity: "localhost".into(), - details: format!("RCPT TO:<{}>", rcpt.address).into(), + details: format!("RCPT TO:<{}>", rcpt.address), }, response: Response { code: 550, diff --git a/crates/smtp/src/outbound/lookup.rs b/crates/smtp/src/outbound/lookup.rs index 088f3023..5536e586 100644 --- a/crates/smtp/src/outbound/lookup.rs +++ b/crates/smtp/src/outbound/lookup.rs @@ -149,7 +149,7 @@ impl DnsLookup for Server { } else { Status::TemporaryFailure(Error::ConnectionError(ErrorDetails { entity: remote_host.hostname().into(), - details: format!("lookup error: {err}").into(), + details: format!("lookup error: {err}"), })) } })?; @@ -205,13 +205,10 @@ impl DnsLookup for Server { Ok(result) } else { - Err(Status::TemporaryFailure(Error::DnsError( - format!( - "No IP addresses found for {:?}.", - envelope.resolve_variable(V_MX).to_string() - ) - .into(), - ))) + Err(Status::TemporaryFailure(Error::DnsError(format!( + "No IP addresses found for {:?}.", + envelope.resolve_variable(V_MX).to_string() + )))) } } } diff --git a/crates/smtp/src/outbound/mod.rs b/crates/smtp/src/outbound/mod.rs index f4335bb1..2ca10926 100644 --- a/crates/smtp/src/outbound/mod.rs +++ b/crates/smtp/src/outbound/mod.rs @@ -10,7 +10,7 @@ use common::config::{ server::ServerProtocol, smtp::queue::{RelayHost, RequireOptional}, }; -use compact_str::ToCompactString; + use mail_send::Credentials; use smtp_proto::{Response, Severity}; @@ -45,7 +45,7 @@ impl Status<(), Error> { | mail_send::Error::Timeout => { Status::TemporaryFailure(Error::ConnectionError(ErrorDetails { entity: hostname.into(), - details: err.to_compact_string(), + details: err.to_string(), })) } @@ -73,7 +73,7 @@ impl Status<(), Error> { | mail_send::Error::MissingStartTls => { Status::PermanentFailure(Error::ConnectionError(ErrorDetails { entity: hostname.into(), - details: err.to_compact_string(), + details: err.to_string(), })) } } @@ -120,11 +120,11 @@ impl Status<(), Error> { })), mail_send::Error::Tls(err) => Status::TemporaryFailure(Error::TlsError(ErrorDetails { entity: hostname.into(), - details: format!("Handshake failed: {err}").into(), + details: format!("Handshake failed: {err}"), })), mail_send::Error::Io(err) => Status::TemporaryFailure(Error::TlsError(ErrorDetails { entity: hostname.into(), - details: format!("I/O error: {err}").into(), + details: format!("I/O error: {err}"), })), _ => Status::PermanentFailure(Error::TlsError(ErrorDetails { entity: hostname.into(), @@ -136,7 +136,7 @@ impl Status<(), Error> { pub fn timeout(hostname: &str, stage: &str) -> Self { Status::TemporaryFailure(Error::ConnectionError(ErrorDetails { entity: hostname.into(), - details: format!("Timeout while {stage}").into(), + details: format!("Timeout while {stage}"), })) } @@ -151,10 +151,10 @@ impl Status<(), Error> { impl From for Status<(), Error> { fn from(err: mail_auth::Error) -> Self { match &err { - mail_auth::Error::DnsRecordNotFound(code) => Status::PermanentFailure(Error::DnsError( - format!("Domain not found: {code:?}").into(), - )), - _ => Status::TemporaryFailure(Error::DnsError(err.to_compact_string())), + mail_auth::Error::DnsRecordNotFound(code) => { + Status::PermanentFailure(Error::DnsError(format!("Domain not found: {code:?}"))) + } + _ => Status::TemporaryFailure(Error::DnsError(err.to_string())), } } } @@ -164,14 +164,14 @@ impl From for Status<(), Error> { match &err { mta_sts::Error::Dns(err) => match err { mail_auth::Error::DnsRecordNotFound(code) => Status::PermanentFailure( - Error::MtaStsError(format!("Record not found: {code:?}").into()), + Error::MtaStsError(format!("Record not found: {code:?}")), ), mail_auth::Error::InvalidRecordType => Status::PermanentFailure( Error::MtaStsError("Failed to parse MTA-STS DNS record.".into()), ), - _ => Status::TemporaryFailure(Error::MtaStsError( - format!("DNS lookup error: {err}").into(), - )), + _ => { + Status::TemporaryFailure(Error::MtaStsError(format!("DNS lookup error: {err}"))) + } }, mta_sts::Error::Http(err) => { if err.is_timeout() { @@ -191,7 +191,7 @@ impl From for Status<(), Error> { } } mta_sts::Error::InvalidPolicy(err) => Status::PermanentFailure(Error::MtaStsError( - format!("Failed to parse policy: {err}").into(), + format!("Failed to parse policy: {err}"), )), } } diff --git a/crates/smtp/src/queue/dsn.rs b/crates/smtp/src/queue/dsn.rs index 8c156244..a607765f 100644 --- a/crates/smtp/src/queue/dsn.rs +++ b/crates/smtp/src/queue/dsn.rs @@ -5,7 +5,7 @@ */ use common::Server; -use compact_str::CompactString; + use mail_builder::MessageBuilder; use mail_builder::headers::HeaderType; use mail_builder::headers::content_type::ContentType; @@ -348,15 +348,15 @@ impl Message { let from_name = server .eval_if(&config.dsn.name, self, self.span_id) .await - .unwrap_or_else(|| CompactString::from("Mail Delivery Subsystem")); + .unwrap_or_else(|| String::from("Mail Delivery Subsystem")); let from_addr = server .eval_if(&config.dsn.address, self, self.span_id) .await - .unwrap_or_else(|| CompactString::from("MAILER-DAEMON@localhost")); + .unwrap_or_else(|| String::from("MAILER-DAEMON@localhost")); let reporting_mta = server .eval_if(&server.core.smtp.report.submitter, self, self.span_id) .await - .unwrap_or_else(|| CompactString::from("localhost")); + .unwrap_or_else(|| String::from("localhost")); // Prepare DSN let mut dsn_header = String::with_capacity(dsn.len() + 128); diff --git a/crates/smtp/src/queue/mod.rs b/crates/smtp/src/queue/mod.rs index 34f5316c..00772523 100644 --- a/crates/smtp/src/queue/mod.rs +++ b/crates/smtp/src/queue/mod.rs @@ -11,7 +11,8 @@ use std::{ }; use common::expr::{self, functions::ResolveVariable, *}; -use compact_str::{CompactString, ToCompactString}; + +use compact_str::ToCompactString; use smtp_proto::{ArchivedResponse, Response}; use store::{SERIALIZE_QUEUEMSG_V1, SerializedVersion, write::now}; use utils::BlobHash; @@ -51,14 +52,14 @@ pub struct Message { pub created: u64, pub blob_hash: BlobHash, - pub return_path: CompactString, - pub return_path_lcase: CompactString, - pub return_path_domain: CompactString, + pub return_path: String, + pub return_path_lcase: String, + pub return_path_domain: String, pub recipients: Vec, pub domains: Vec, pub flags: u64, - pub env_id: Option, + pub env_id: Option, pub priority: i16, pub size: u64, @@ -82,7 +83,7 @@ pub enum QuotaKey { #[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq)] pub struct Domain { - pub domain: CompactString, + pub domain: String, pub retry: Schedule, pub notify: Schedule, pub expires: u64, @@ -92,11 +93,11 @@ pub struct Domain { #[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq)] pub struct Recipient { pub domain_idx: u32, - pub address: CompactString, - pub address_lcase: CompactString, + pub address: String, + pub address_lcase: String, pub status: Status, HostResponse>, pub flags: u64, - pub orcpt: Option, + pub orcpt: Option, } pub const RCPT_DSN_SENT: u64 = 1 << 32; @@ -132,23 +133,23 @@ pub struct HostResponse { #[derive(Debug, Clone, PartialEq, Eq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)] pub enum Error { - DnsError(CompactString), + DnsError(String), UnexpectedResponse(HostResponse), ConnectionError(ErrorDetails), TlsError(ErrorDetails), DaneError(ErrorDetails), - MtaStsError(CompactString), + MtaStsError(String), RateLimited, ConcurrencyLimited, - Io(CompactString), + Io(String), } #[derive( Debug, Clone, PartialEq, Eq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Default, )] pub struct ErrorDetails { - pub entity: CompactString, - pub details: CompactString, + pub entity: String, + pub details: String, } impl Ord for Schedule { @@ -495,7 +496,7 @@ impl Display for Status<(), Error> { } } -impl Display for Status, HostResponse> { +impl Display for Status, HostResponse> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Status::Scheduled => write!(f, "Scheduled"), diff --git a/crates/smtp/src/queue/spool.rs b/crates/smtp/src/queue/spool.rs index 61c19511..1183b060 100644 --- a/crates/smtp/src/queue/spool.rs +++ b/crates/smtp/src/queue/spool.rs @@ -7,7 +7,7 @@ use crate::queue::DomainPart; use common::ipc::QueueEvent; use common::{KV_LOCK_QUEUE_MESSAGE, Server}; -use compact_str::CompactString; + use std::borrow::Cow; use std::future::Future; use std::time::{Duration, SystemTime}; @@ -30,9 +30,9 @@ pub const QUEUE_REFRESH: u64 = 300; pub trait SmtpSpool: Sync + Send { fn new_message( &self, - return_path: impl Into, - return_path_lcase: impl Into, - return_path_domain: impl Into, + return_path: impl Into, + return_path_lcase: impl Into, + return_path_domain: impl Into, span_id: u64, ) -> Message; @@ -53,9 +53,9 @@ pub trait SmtpSpool: Sync + Send { impl SmtpSpool for Server { fn new_message( &self, - return_path: impl Into, - return_path_lcase: impl Into, - return_path_domain: impl Into, + return_path: impl Into, + return_path_lcase: impl Into, + return_path_domain: impl Into, span_id: u64, ) -> Message { let created = SystemTime::now() @@ -262,7 +262,7 @@ impl Message { To = self .recipients .iter() - .map(|r| trc::Value::String(r.address_lcase.clone())) + .map(|r| trc::Value::String(r.address_lcase.as_str().into())) .collect::>(), Size = self.size, NextRetry = trc::Value::Timestamp(self.next_delivery_event()), @@ -359,9 +359,9 @@ impl Message { pub async fn add_recipient_parts( &mut self, - rcpt: impl Into, - rcpt_lcase: impl Into, - rcpt_domain: impl Into, + rcpt: impl Into, + rcpt_lcase: impl Into, + rcpt_domain: impl Into, server: &Server, ) { let rcpt_domain = rcpt_domain.into(); @@ -405,7 +405,7 @@ impl Message { }); } - pub async fn add_recipient(&mut self, rcpt: impl Into, server: &Server) { + pub async fn add_recipient(&mut self, rcpt: impl Into, server: &Server) { let rcpt = rcpt.into(); let rcpt_lcase = rcpt.to_lowercase(); let rcpt_domain = rcpt_lcase.domain_part().to_string(); @@ -514,7 +514,7 @@ impl Message { } } - pub fn has_domain(&self, domains: &[CompactString]) -> bool { + pub fn has_domain(&self, domains: &[String]) -> bool { self.domains.iter().any(|d| domains.contains(&d.domain)) || self .return_path @@ -524,7 +524,7 @@ impl Message { } impl ArchivedMessage { - pub fn has_domain(&self, domains: &[CompactString]) -> bool { + pub fn has_domain(&self, domains: &[String]) -> bool { self.domains .iter() .any(|d| domains.iter().any(|dd| dd == d.domain.as_str())) diff --git a/crates/smtp/src/reporting/analysis.rs b/crates/smtp/src/reporting/analysis.rs index a8f1206e..1d480513 100644 --- a/crates/smtp/src/reporting/analysis.rs +++ b/crates/smtp/src/reporting/analysis.rs @@ -12,7 +12,7 @@ use std::{ use ahash::AHashMap; use common::Server; -use compact_str::CompactString; + use mail_auth::{ flate2::read::GzDecoder, report::{ActionDisposition, DmarcResult, Feedback, Report, tlsrpt::TlsReport}, @@ -46,9 +46,9 @@ struct ReportData<'x> { #[derive(serde::Serialize, serde::Deserialize)] pub struct IncomingReport { - pub from: CompactString, - pub to: Vec, - pub subject: CompactString, + pub from: String, + pub to: Vec, + pub subject: String, pub report: T, } @@ -60,19 +60,19 @@ impl AnalyzeReport for Server { fn analyze_report(&self, message: Message<'static>, session_id: u64) { let core = self.clone(); tokio::spawn(async move { - let from: CompactString = message + let from: String = message .from() .and_then(|a| a.last()) .and_then(|a| a.address()) .unwrap_or_default() .into(); - let to: Vec = message.to().map_or_else(Vec::new, |a| { + let to: Vec = message.to().map_or_else(Vec::new, |a| { a.iter() .filter_map(|a| a.address()) .map(|a| a.into()) .collect() }); - let subject: CompactString = message.subject().unwrap_or_default().into(); + let subject: String = message.subject().unwrap_or_default().into(); let mut reports = Vec::new(); for part in &message.parts { @@ -496,7 +496,7 @@ impl LogReport for Feedback<'_> { } impl IncomingReport { - pub fn has_domain(&self, domain: &[CompactString]) -> bool { + pub fn has_domain(&self, domain: &[String]) -> bool { self.to .iter() .any(|to| domain.iter().any(|d| to.ends_with(d.as_str()))) diff --git a/crates/smtp/src/reporting/dkim.rs b/crates/smtp/src/reporting/dkim.rs index 685b0e7c..dc2c5c8d 100644 --- a/crates/smtp/src/reporting/dkim.rs +++ b/crates/smtp/src/reporting/dkim.rs @@ -5,7 +5,7 @@ */ use common::listener::SessionStream; -use compact_str::ToCompactString; + use mail_auth::{ AuthenticatedMessage, AuthenticationResults, DkimOutput, common::verify::VerifySignature, }; @@ -50,7 +50,7 @@ impl Session { .server .eval_if(&config.address, self, self.data.session_id) .await - .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_compact_string()); + .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_string()); let mut report = Vec::with_capacity(128); self.new_auth_failure(output.result().into(), rejected) .with_authentication_results( @@ -67,7 +67,7 @@ impl Session { self.server .eval_if(&config.name, self, self.data.session_id) .await - .unwrap_or_else(|| "Mail Delivery Subsystem".to_compact_string()) + .unwrap_or_else(|| "Mail Delivery Subsystem".to_string()) .as_str(), from_addr.as_str(), ), @@ -76,7 +76,7 @@ impl Session { .server .eval_if(&config.subject, self, self.data.session_id) .await - .unwrap_or_else(|| "DKIM Report".to_compact_string()), + .unwrap_or_else(|| "DKIM Report".to_string()), &mut report, ) .ok(); diff --git a/crates/smtp/src/reporting/dmarc.rs b/crates/smtp/src/reporting/dmarc.rs index fe8df435..3e90a392 100644 --- a/crates/smtp/src/reporting/dmarc.rs +++ b/crates/smtp/src/reporting/dmarc.rs @@ -13,7 +13,8 @@ use common::{ ipc::{DmarcEvent, ToHash}, listener::SessionStream, }; -use compact_str::{CompactString, ToCompactString}; + +use compact_str::ToCompactString; use mail_auth::{ ArcOutput, AuthenticatedMessage, AuthenticationResults, DkimOutput, DkimResult, DmarcOutput, SpfResult, @@ -497,7 +498,7 @@ impl DmarcReporting for Server { .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_compact_string()), ); if let Some(org_name) = self - .eval_if::( + .eval_if::( &config.org_name, &RecipientDomain::new(event.domain.as_str()), span_id, @@ -507,7 +508,7 @@ impl DmarcReporting for Server { report = report.with_org_name(org_name); } if let Some(contact_info) = self - .eval_if::( + .eval_if::( &config.contact_info, &RecipientDomain::new(event.domain.as_str()), span_id, diff --git a/crates/smtp/src/reporting/mod.rs b/crates/smtp/src/reporting/mod.rs index aee6a2cf..3c8be044 100644 --- a/crates/smtp/src/reporting/mod.rs +++ b/crates/smtp/src/reporting/mod.rs @@ -12,7 +12,7 @@ use common::{ expr::if_block::IfBlock, ipc::ReportingEvent, }; -use compact_str::CompactString; + use mail_auth::{ common::headers::HeaderWriter, report::{AuthFailureType, DeliveryResult, Feedback, FeedbackType}, @@ -87,8 +87,8 @@ pub trait SmtpReporting: Sync + Send { fn send_autogenerated( &self, - from_addr: impl Into + Sync + Send, - rcpts: impl Iterator + Sync + Send> + Sync + Send, + from_addr: impl Into + Sync + Send, + rcpts: impl Iterator + Sync + Send> + Sync + Send, raw_message: Vec, sign_config: Option<&IfBlock>, parent_session_id: u64, @@ -162,8 +162,8 @@ impl SmtpReporting for Server { async fn send_autogenerated( &self, - from_addr: impl Into + Sync + Send, - rcpts: impl Iterator + Sync + Send> + Sync + Send, + from_addr: impl Into + Sync + Send, + rcpts: impl Iterator + Sync + Send> + Sync + Send, raw_message: Vec, sign_config: Option<&IfBlock>, parent_session_id: u64, @@ -219,7 +219,7 @@ impl SmtpReporting for Server { bytes: &[u8], ) -> Option> { let signers = self - .eval_if::, _>(config, message, message.span_id) + .eval_if::, _>(config, message, message.span_id) .await .unwrap_or_default(); if !signers.is_empty() { diff --git a/crates/smtp/src/reporting/spf.rs b/crates/smtp/src/reporting/spf.rs index c37794bd..242aa3c8 100644 --- a/crates/smtp/src/reporting/spf.rs +++ b/crates/smtp/src/reporting/spf.rs @@ -5,7 +5,7 @@ */ use common::listener::SessionStream; -use compact_str::ToCompactString; + use mail_auth::{AuthenticationResults, SpfOutput, report::AuthFailureType}; use trc::OutgoingReportEvent; use utils::config::Rate; @@ -41,7 +41,7 @@ impl Session { .server .eval_if(&config.address, self, self.data.session_id) .await - .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_compact_string()); + .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_string()); let mut report = Vec::with_capacity(128); self.new_auth_failure(AuthFailureType::Spf, rejected) .with_authentication_results( @@ -67,7 +67,7 @@ impl Session { self.server .eval_if(&config.name, self, self.data.session_id) .await - .unwrap_or_else(|| "Mailer Daemon".to_compact_string()) + .unwrap_or_else(|| "Mailer Daemon".to_string()) .as_str(), from_addr.as_str(), ), @@ -76,7 +76,7 @@ impl Session { .server .eval_if(&config.subject, self, self.data.session_id) .await - .unwrap_or_else(|| "SPF Report".to_compact_string()), + .unwrap_or_else(|| "SPF Report".to_string()), &mut report, ) .ok(); diff --git a/crates/smtp/src/reporting/tls.rs b/crates/smtp/src/reporting/tls.rs index 3d89f26e..30ae61e4 100644 --- a/crates/smtp/src/reporting/tls.rs +++ b/crates/smtp/src/reporting/tls.rs @@ -15,7 +15,7 @@ use common::{ }, ipc::{TlsEvent, ToHash}, }; -use compact_str::{CompactString, ToCompactString}; + use mail_auth::{ flate2::{Compression, write::GzEncoder}, mta_sts::{ReportUri, TlsRpt}, @@ -211,7 +211,7 @@ impl TlsReporting for Server { let from_addr = self .eval_if(&config.address, &RecipientDomain::new(domain_name), span_id) .await - .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_compact_string()); + .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_string()); let mut message = Vec::with_capacity(2048); let _ = report.write_rfc5322_from_bytes( domain_name, @@ -222,11 +222,11 @@ impl TlsReporting for Server { span_id, ) .await - .unwrap_or_else(|| "localhost".to_compact_string()), + .unwrap_or_else(|| "localhost".to_string()), ( self.eval_if(&config.name, &RecipientDomain::new(domain_name), span_id) .await - .unwrap_or_else(|| "Mail Delivery Subsystem".to_compact_string()) + .unwrap_or_else(|| "Mail Delivery Subsystem".to_string()) .as_str(), from_addr.as_str(), ), @@ -268,26 +268,24 @@ impl TlsReporting for Server { let config = &self.core.smtp.report.tls; let mut report = TlsReport { organization_name: self - .eval_if::( + .eval_if::( &config.org_name, &RecipientDomain::new(domain_name), span_id, ) .await - .map(Into::into) .clone(), date_range: DateRange { start_datetime: DateTime::from_timestamp(event_from as i64), end_datetime: DateTime::from_timestamp(event_to as i64), }, contact_info: self - .eval_if::( + .eval_if::( &config.contact_info, &RecipientDomain::new(domain_name), span_id, ) .await - .map(Into::into) .clone(), report_id: format!("{}_{}", event_from, policy), policies: Vec::with_capacity(events.len()), diff --git a/crates/smtp/src/scripts/envelope.rs b/crates/smtp/src/scripts/envelope.rs index 1d4c106f..da9afed9 100644 --- a/crates/smtp/src/scripts/envelope.rs +++ b/crates/smtp/src/scripts/envelope.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::CompactString; use sieve::Envelope; use smtp_proto::{ MAIL_BY_NOTIFY, MAIL_BY_RETURN, MAIL_BY_TRACE, MAIL_RET_FULL, MAIL_RET_HDRS, RCPT_NOTIFY_DELAY, @@ -17,19 +16,15 @@ use crate::{ }; impl SessionData { - pub fn apply_envelope_modification(&mut self, envelope: Envelope, value: CompactString) { + pub fn apply_envelope_modification(&mut self, envelope: Envelope, value: String) { match envelope { Envelope::From => { let (address, address_lcase, domain) = if value.contains('@') { - let address_lcase = CompactString::from_str_to_lowercase(&value); + let address_lcase = value.to_lowercase(); let domain = address_lcase.domain_part().into(); (value, address_lcase, domain) } else if value.is_empty() { - ( - CompactString::new(""), - CompactString::new(""), - CompactString::new(""), - ) + (String::new(), String::new(), String::new()) } else { return; }; diff --git a/crates/smtp/src/scripts/event_loop.rs b/crates/smtp/src/scripts/event_loop.rs index 060a1330..3669202f 100644 --- a/crates/smtp/src/scripts/event_loop.rs +++ b/crates/smtp/src/scripts/event_loop.rs @@ -7,7 +7,7 @@ use std::{borrow::Cow, future::Future, sync::Arc, time::Instant}; use common::{Server, scripts::plugins::PluginContext}; -use compact_str::CompactString; + use mail_auth::common::headers::HeaderWriter; use mail_parser::{Encoding, Message, MessagePart, PartType}; use sieve::{ @@ -30,7 +30,7 @@ use super::{ScriptModification, ScriptParameters, ScriptResult}; pub trait RunScript: Sync + Send { fn run_script( &self, - script_id: CompactString, + script_id: String, script: Arc, params: ScriptParameters<'_>, ) -> impl Future + Send; @@ -39,7 +39,7 @@ pub trait RunScript: Sync + Send { impl RunScript for Server { async fn run_script( &self, - script_id: CompactString, + script_id: String, script: Arc, params: ScriptParameters<'_>, ) -> ScriptResult { @@ -346,7 +346,7 @@ impl RunScript for Server { Event::SetEnvelope { envelope, value } => { modifications.push(ScriptModification::SetEnvelope { name: envelope, - value: value.into(), + value, }); input = true.into(); } @@ -405,9 +405,9 @@ impl RunScript for Server { && matches!(reject_bytes.next(), Some(ch) if ch.is_ascii_digit()) && matches!(reject_bytes.next(), Some(ch) if ch == &b' ' ) { - ScriptResult::Reject(reject_reason.into()) + ScriptResult::Reject(reject_reason) } else { - ScriptResult::Reject(format!("503 5.5.3 {reject_reason}").into()) + ScriptResult::Reject(format!("503 5.5.3 {reject_reason}")) } } else if keep_id != usize::MAX - 1 { if let Some(message) = messages.into_iter().nth(keep_id - 1) { diff --git a/crates/smtp/src/scripts/exec.rs b/crates/smtp/src/scripts/exec.rs index fcb9f31b..f13e9d68 100644 --- a/crates/smtp/src/scripts/exec.rs +++ b/crates/smtp/src/scripts/exec.rs @@ -7,7 +7,7 @@ use std::{sync::Arc, time::SystemTime}; use common::listener::SessionStream; -use compact_str::CompactString; + use mail_auth::common::resolver::ToReverseName; use sieve::{Envelope, Sieve, runtime::Variable}; use smtp_proto::*; @@ -142,7 +142,7 @@ impl Session { pub async fn run_script( &self, - script_id: CompactString, + script_id: String, script: Arc, params: ScriptParameters<'_>, ) -> ScriptResult { diff --git a/crates/smtp/src/scripts/mod.rs b/crates/smtp/src/scripts/mod.rs index 0e9aff04..af1f6003 100644 --- a/crates/smtp/src/scripts/mod.rs +++ b/crates/smtp/src/scripts/mod.rs @@ -10,7 +10,7 @@ use ahash::AHashMap; use common::{ Server, auth::AccessToken, expr::functions::ResolveVariable, scripts::ScriptModification, }; -use compact_str::CompactString; + use mail_parser::Message; use sieve::{Envelope, runtime::Variable}; @@ -27,7 +27,7 @@ pub enum ScriptResult { message: Vec, modifications: Vec, }, - Reject(CompactString), + Reject(String), Discard, } @@ -36,10 +36,10 @@ pub struct ScriptParameters<'x> { headers: Option<&'x [u8]>, variables: AHashMap, Variable>, envelope: Vec<(Envelope, Variable)>, - from_addr: CompactString, - from_name: CompactString, - return_path: CompactString, - sign: Vec, + from_addr: String, + from_name: String, + return_path: String, + sign: Vec, access_token: Option<&'x AccessToken>, session_id: u64, } diff --git a/crates/store/src/backend/http/lookup.rs b/crates/store/src/backend/http/lookup.rs index bb5c6104..dbaa932e 100644 --- a/crates/store/src/backend/http/lookup.rs +++ b/crates/store/src/backend/http/lookup.rs @@ -11,6 +11,7 @@ use std::{ }; use ahash::AHashMap; +use compact_str::ToCompactString; use rand::seq::IndexedRandom; use utils::HttpLimitResponse; @@ -102,7 +103,7 @@ impl HttpStore { trc::StoreEvent::HttpStoreError .into_err() .reason(err) - .ctx(trc::Key::Url, self.config.url.to_string()) + .ctx(trc::Key::Url, self.config.url.to_compact_string()) .details("Failed to build request") })?; @@ -111,7 +112,7 @@ impl HttpStore { trc::StoreEvent::HttpStoreError .into_err() .ctx(trc::Key::Code, response.status().as_u16()) - .ctx(trc::Key::Url, self.config.url.to_string()) + .ctx(trc::Key::Url, self.config.url.to_compact_string()) .ctx(trc::Key::Elapsed, time.elapsed()) .details("Failed to fetch HTTP list") ); @@ -124,14 +125,14 @@ impl HttpStore { trc::StoreEvent::HttpStoreError .into_err() .reason(err) - .ctx(trc::Key::Url, self.config.url.to_string()) + .ctx(trc::Key::Url, self.config.url.to_compact_string()) .ctx(trc::Key::Elapsed, time.elapsed()) .details("Failed to fetch resource") })? .ok_or_else(|| { trc::StoreEvent::HttpStoreError .into_err() - .ctx(trc::Key::Url, self.config.url.to_string()) + .ctx(trc::Key::Url, self.config.url.to_compact_string()) .ctx(trc::Key::Elapsed, time.elapsed()) .details("Resource is too large") })?; @@ -148,7 +149,7 @@ impl HttpStore { trc::StoreEvent::HttpStoreError .into_err() .reason(err) - .ctx(trc::Key::Url, self.config.url.to_string()) + .ctx(trc::Key::Url, self.config.url.to_compact_string()) .ctx(trc::Key::Elapsed, time.elapsed()) .details("Failed to read line") })?; @@ -222,7 +223,7 @@ impl HttpStore { trc::event!( Store(trc::StoreEvent::HttpStoreFetch), - Url = self.config.url.to_string(), + Url = self.config.url.to_compact_string(), Total = entries.len(), Elapsed = time.elapsed(), ); diff --git a/crates/store/src/dispatch/store.rs b/crates/store/src/dispatch/store.rs index 6b5f925e..aefd12f8 100644 --- a/crates/store/src/dispatch/store.rs +++ b/crates/store/src/dispatch/store.rs @@ -9,6 +9,7 @@ use std::{ time::Instant, }; +use compact_str::ToCompactString; use roaring::RoaringBitmap; use trc::{AddContext, StoreEvent}; @@ -175,7 +176,7 @@ impl Store { trc::event!( Store(trc::StoreEvent::SqlQuery), - Details = query.to_string(), + Details = query.to_compact_string(), Value = params.as_slice(), Result = &result, ); diff --git a/crates/store/src/lib.rs b/crates/store/src/lib.rs index 68f8f856..1fa794fd 100644 --- a/crates/store/src/lib.rs +++ b/crates/store/src/lib.rs @@ -15,7 +15,7 @@ pub mod write; pub use ahash; pub use blake3; -use compact_str::CompactString; + pub use gxhash; pub use parking_lot; pub use rand; @@ -657,30 +657,30 @@ impl From> for Value<'_> { } impl Value<'_> { - pub fn into_string(self) -> CompactString { + pub fn into_string(self) -> String { match self { - Value::Text(s) => s.as_ref().into(), - Value::Integer(i) => i.to_string().into(), - Value::Bool(b) => b.to_string().into(), - Value::Float(f) => f.to_string().into(), - Value::Blob(b) => CompactString::from_utf8_lossy(b.as_ref()), + Value::Text(s) => s.into_owned(), + Value::Integer(i) => i.to_string(), + Value::Bool(b) => b.to_string(), + Value::Float(f) => f.to_string(), + Value::Blob(b) => String::from_utf8_lossy(b.as_ref()).into_owned(), Value::Null => "".into(), } } - pub fn into_lower_string(self) -> CompactString { + pub fn into_lower_string(self) -> String { match self { - Value::Text(s) => CompactString::from_str_to_lowercase(s.as_ref()), - Value::Integer(i) => i.to_string().into(), - Value::Bool(b) => b.to_string().into(), - Value::Float(f) => f.to_string().into(), - Value::Blob(b) => CompactString::from_utf8_lossy(b.as_ref()).to_lowercase(), + Value::Text(s) => s.as_ref().to_lowercase(), + Value::Integer(i) => i.to_string(), + Value::Bool(b) => b.to_string(), + Value::Float(f) => f.to_string(), + Value::Blob(b) => String::from_utf8_lossy(b.as_ref()).to_lowercase(), Value::Null => "".into(), } } } -impl From for Vec { +impl From for Vec { fn from(value: Row) -> Self { value.values.into_iter().map(|v| v.into_string()).collect() } @@ -702,7 +702,7 @@ impl From for Vec { } } -impl From for Vec { +impl From for Vec { fn from(value: Rows) -> Self { value .rows diff --git a/crates/store/src/write/serialize.rs b/crates/store/src/write/serialize.rs index 007914e3..0cec9930 100644 --- a/crates/store/src/write/serialize.rs +++ b/crates/store/src/write/serialize.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +use compact_str::format_compact; use rkyv::util::AlignedVec; use crate::{Deserialize, Serialize, SerializeInfallible, SerializedVersion, U32_LEN, Value}; @@ -218,7 +219,7 @@ impl Archive { } else { Err(trc::StoreEvent::DataCorruption .into_err() - .details(format!( + .details(format_compact!( "Archive version mismatch, expected {} ({} bytes) but got {} ({} bytes)", T::serialize_version(), std::mem::size_of::(), @@ -251,7 +252,7 @@ impl Archive { } else { Err(trc::StoreEvent::DataCorruption .into_err() - .details(format!( + .details(format_compact!( "Archive version mismatch, expected {} ({} bytes) but got {} ({} bytes)", T::serialize_version(), std::mem::size_of::(), diff --git a/crates/trc/src/event/conv.rs b/crates/trc/src/event/conv.rs index 91825090..41366933 100644 --- a/crates/trc/src/event/conv.rs +++ b/crates/trc/src/event/conv.rs @@ -6,7 +6,7 @@ use std::{borrow::Cow, fmt::Debug, str::FromStr, time::Duration}; -use compact_str::CompactString; +use compact_str::{CompactString, ToCompactString, format_compact}; use mail_auth::common::verify::VerifySignature; use crate::*; @@ -25,7 +25,7 @@ impl From<&'static str> for Value { impl From for Value { fn from(value: String) -> Self { - Self::String(value.into()) + Self::String(CompactString::from_string_buffer(value)) } } @@ -158,7 +158,7 @@ where { fn from(value: &crate::Result) -> Self { match value { - Ok(value) => format!("{:?}", value).into(), + Ok(value) => format_compact!("{:?}", value).into(), Err(err) => Value::Event(err.clone()), } } @@ -197,7 +197,10 @@ impl EventType { pub fn from_http_error(self, err: reqwest::Error) -> Error { self.into_err() - .ctx_opt(Key::Url, err.url().map(|url| url.as_ref().to_string())) + .ctx_opt( + Key::Url, + err.url().map(|url| url.as_ref().to_compact_string()), + ) .ctx_opt(Key::Code, err.status().map(|status| status.as_u16())) .reason(err) } @@ -226,10 +229,10 @@ impl From for Error { } mail_auth::Error::CryptoError(details) => EventType::MailAuth(MailAuthEvent::Crypto) .into_err() - .details(details), + .details(CompactString::from(details)), mail_auth::Error::Io(details) => EventType::MailAuth(MailAuthEvent::Io) .into_err() - .details(details), + .details(CompactString::from(details)), mail_auth::Error::Base64 => EventType::MailAuth(MailAuthEvent::Base64).into_err(), mail_auth::Error::UnsupportedVersion => { EventType::Dkim(DkimEvent::UnsupportedVersion).into_err() @@ -266,7 +269,7 @@ impl From for Error { } mail_auth::Error::DnsError(details) => EventType::MailAuth(MailAuthEvent::DnsError) .into_err() - .details(details), + .details(CompactString::from(details)), mail_auth::Error::DnsRecordNotFound(code) => { EventType::MailAuth(MailAuthEvent::DnsRecordNotFound) .into_err() @@ -332,7 +335,7 @@ impl From<&mail_auth::DkimOutput<'_>> for Error { fn from(value: &mail_auth::DkimOutput<'_>) -> Self { Error::from(value.result()).ctx_opt( Key::Domain, - value.signature().map(|s| s.domain().to_string()), + value.signature().map(|s| s.domain().to_compact_string()), ) } } @@ -374,7 +377,10 @@ impl From<&mail_auth::SpfOutput> for Error { mail_auth::SpfResult::TempError => SpfEvent::TempError, mail_auth::SpfResult::None => SpfEvent::None, })) - .ctx_opt(Key::Details, value.explanation().map(|s| s.to_string())) + .ctx_opt( + Key::Details, + value.explanation().map(|s| s.to_compact_string()), + ) } } @@ -405,7 +411,7 @@ impl AssertSuccess for reqwest::Response { Err(cause .ctx(Key::Code, status.as_u16()) .details("HTTP request failed") - .ctx_opt(Key::Reason, self.text().await.ok())) + .ctx_opt(Key::Reason, self.text().await.map(CompactString::from).ok())) } } } diff --git a/crates/trc/src/event/mod.rs b/crates/trc/src/event/mod.rs index b5bb2828..67e867cf 100644 --- a/crates/trc/src/event/mod.rs +++ b/crates/trc/src/event/mod.rs @@ -9,6 +9,7 @@ pub mod description; pub mod level; pub mod metrics; +use compact_str::ToCompactString; use std::fmt::Display; use crate::*; @@ -131,7 +132,7 @@ impl Error { #[inline(always)] pub fn reason(self, error: impl Display) -> Self { - self.ctx(Key::Reason, error.to_string()) + self.ctx(Key::Reason, error.to_compact_string()) } #[inline(always)] diff --git a/crates/trc/src/serializers/binary.rs b/crates/trc/src/serializers/binary.rs index 3e384167..1cf01cc4 100644 --- a/crates/trc/src/serializers/binary.rs +++ b/crates/trc/src/serializers/binary.rs @@ -10,6 +10,8 @@ use std::net::{Ipv4Addr, Ipv6Addr}; +use compact_str::format_compact; + use crate::*; const VERSION: u8 = 1; @@ -51,7 +53,7 @@ pub fn deserialize_events(bytes: &[u8]) -> crate::Result events.push(Event::deserialize(&mut iter).ok_or_else(|| { StoreEvent::DataCorruption .caused_by(crate::location!()) - .details(format!("Failed to deserialize event {n}")) + .details(format_compact!("Failed to deserialize event {n}")) })?); } Ok(events) diff --git a/crates/utils/src/config/mod.rs b/crates/utils/src/config/mod.rs index 649bc89a..b9a965cb 100644 --- a/crates/utils/src/config/mod.rs +++ b/crates/utils/src/config/mod.rs @@ -12,6 +12,7 @@ pub mod utils; use std::{collections::BTreeMap, time::Duration}; use ahash::AHashMap; +use compact_str::CompactString; use serde::Serialize; #[derive(Debug, Default, Serialize)] @@ -190,7 +191,11 @@ impl Config { ), }; - trc::error!(trc::EventType::Config(cause).into_err().details(message)); + trc::error!( + trc::EventType::Config(cause) + .into_err() + .details(CompactString::from(message)) + ); } } @@ -222,7 +227,11 @@ impl Config { ), }; - trc::error!(trc::EventType::Config(cause).into_err().details(message)); + trc::error!( + trc::EventType::Config(cause) + .into_err() + .details(CompactString::from(message)) + ); } } } diff --git a/crates/utils/src/config/utils.rs b/crates/utils/src/config/utils.rs index 4ed29c53..861fb20f 100644 --- a/crates/utils/src/config/utils.rs +++ b/crates/utils/src/config/utils.rs @@ -11,7 +11,6 @@ use std::{ time::Duration, }; -use compact_str::CompactString; use mail_auth::{ IpLookupStrategy, common::crypto::{Algorithm, HashAlgorithm}, @@ -639,26 +638,6 @@ impl AsKey for &str { } } -impl AsKey for CompactString { - fn as_key(&self) -> String { - self.to_string() - } - - fn as_prefix(&self) -> String { - format!("{self}.") - } -} - -impl AsKey for &CompactString { - fn as_key(&self) -> String { - self.to_string() - } - - fn as_prefix(&self) -> String { - format!("{self}.") - } -} - impl AsKey for String { fn as_key(&self) -> String { self.to_string() diff --git a/crates/utils/src/json/parser/json.rs b/crates/utils/src/json/parser/json.rs index 1a1c1ce1..47f07f93 100644 --- a/crates/utils/src/json/parser/json.rs +++ b/crates/utils/src/json/parser/json.rs @@ -6,6 +6,8 @@ use std::{fmt::Display, iter::Peekable, slice::Iter}; +use compact_str::format_compact; + use super::{Ignore, JsonObjectParser, Token}; const MAX_NESTED_LEVELS: u32 = 16; @@ -39,18 +41,18 @@ impl<'x> Parser<'x> { pub fn error(&self, message: &str) -> trc::Error { trc::JmapEvent::NotJson .into_err() - .details(format!("{message} at position {}.", self.pos)) + .details(format_compact!("{message} at position {}.", self.pos)) } pub fn error_unterminated(&self) -> trc::Error { - trc::JmapEvent::NotJson.into_err().details(format!( + trc::JmapEvent::NotJson.into_err().details(format_compact!( "Unterminated string at position {pos}.", pos = self.pos )) } pub fn error_utf8(&self) -> trc::Error { - trc::JmapEvent::NotJson.into_err().details(format!( + trc::JmapEvent::NotJson.into_err().details(format_compact!( "Invalid UTF-8 sequence at position {pos}.", pos = self.pos )) @@ -58,11 +60,13 @@ impl<'x> Parser<'x> { pub fn error_value(&mut self) -> trc::Error { if self.is_eof || self.skip_string() { - trc::JmapEvent::InvalidArguments.into_err().details(format!( - "Invalid value {:?} at position {}.", - String::from_utf8_lossy(self.bytes[self.pos_marker..self.pos - 1].as_ref()), - self.pos - )) + trc::JmapEvent::InvalidArguments + .into_err() + .details(format_compact!( + "Invalid value {:?} at position {}.", + String::from_utf8_lossy(self.bytes[self.pos_marker..self.pos - 1].as_ref()), + self.pos + )) } else { self.error_unterminated() } diff --git a/crates/utils/src/json/parser/mod.rs b/crates/utils/src/json/parser/mod.rs index a4249fb1..59a580c4 100644 --- a/crates/utils/src/json/parser/mod.rs +++ b/crates/utils/src/json/parser/mod.rs @@ -6,6 +6,8 @@ use std::fmt::Display; +use compact_str::format_compact; + use self::json::Parser; pub mod base32; @@ -118,18 +120,24 @@ impl Token { if self == token { Ok(()) } else { - Err(trc::JmapEvent::NotRequest.into_err().details(format!( - "Invalid JMAP request: expected '{token}', got '{self}'." - ))) + Err(trc::JmapEvent::NotRequest + .into_err() + .details(format_compact!( + "Invalid JMAP request: expected '{token}', got '{self}'." + ))) } } pub fn error(&self, property: &str, expected: &str) -> trc::Error { - trc::JmapEvent::InvalidArguments.into_err().details(if !property.is_empty() { - format!("Invalid argument for '{property:?}': expected '{expected}', got '{self}'.",) - } else { - format!("Invalid argument: expected '{expected}', got '{self}'.") - }) + trc::JmapEvent::InvalidArguments + .into_err() + .details(if !property.is_empty() { + format_compact!( + "Invalid argument for '{property:?}': expected '{expected}', got '{self}'.", + ) + } else { + format_compact!("Invalid argument: expected '{expected}', got '{self}'.") + }) } } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index b27a4fcd..a5cabd8b 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -17,7 +17,7 @@ pub mod snowflake; pub mod topological; pub mod url_params; -use compact_str::CompactString; +use compact_str::ToCompactString; use futures::StreamExt; use reqwest::Response; use rustls::{ @@ -215,7 +215,7 @@ impl UnwrapFailure for Option { None => { trc::event!( Server(trc::ServerEvent::StartupError), - Details = message.to_string() + Details = message.to_compact_string() ); eprintln!("{message}"); std::process::exit(1); @@ -231,8 +231,8 @@ impl UnwrapFailure for Result { Err(err) => { trc::event!( Server(trc::ServerEvent::StartupError), - Details = message.to_string(), - Reason = err.to_string() + Details = message.to_compact_string(), + Reason = err.to_compact_string() ); #[cfg(feature = "test_mode")] @@ -251,7 +251,7 @@ impl UnwrapFailure for Result { pub fn failed(message: &str) -> ! { trc::event!( Server(trc::ServerEvent::StartupError), - Details = message.to_string(), + Details = message.to_compact_string(), ); eprintln!("{message}"); std::process::exit(1); @@ -365,8 +365,8 @@ impl ServerCertVerifier for DummyVerifier { } // Basic email sanitizer -pub fn sanitize_email(email: &str) -> Option { - let mut result = CompactString::with_capacity(email.len()); +pub fn sanitize_email(email: &str) -> Option { + let mut result = String::with_capacity(email.len()); let mut found_local = false; let mut found_domain = false; let mut last_ch = char::from(0); diff --git a/tests/src/directory/ldap.rs b/tests/src/directory/ldap.rs index 7d466a9f..2471cfac 100644 --- a/tests/src/directory/ldap.rs +++ b/tests/src/directory/ldap.rs @@ -6,7 +6,6 @@ use std::fmt::Debug; -use compact_str::{CompactString, ToCompactString}; use directory::{ QueryBy, ROLE_USER, Type, backend::{RcptType, internal::manage::ManageDirectory}, @@ -57,10 +56,10 @@ async fn ldap_directory() { member_of: map_account_ids(base_store, vec!["sales"]) .await .into_iter() - .map(|v| v.to_compact_string()) + .map(|v| v.to_string()) .collect(), emails: vec!["john@example.org".into(), "john.doe@example.org".into()], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } .into_sorted() @@ -87,7 +86,7 @@ async fn ldap_directory() { typ: Type::Individual, quota: 500000, emails: vec!["bill@example.org".into(),], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } .into_sorted() @@ -124,10 +123,10 @@ async fn ldap_directory() { member_of: map_account_ids(base_store, vec!["sales", "support"]) .await .into_iter() - .map(|v| v.to_compact_string()) + .map(|v| v.to_string()) .collect(), emails: vec!["jane@example.org".into(),], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } .into_sorted() @@ -146,7 +145,7 @@ async fn ldap_directory() { name: "sales".into(), description: Some("sales".into()), typ: Type::Group, - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -228,11 +227,11 @@ async fn ldap_directory() { ); compare_sorted( core.vrfy(&handle, "info", 0).await.unwrap(), - Vec::::new(), + Vec::::new(), ); compare_sorted( core.vrfy(&handle, "invalid", 0).await.unwrap(), - Vec::::new(), + Vec::::new(), ); // EXPN diff --git a/tests/src/directory/mod.rs b/tests/src/directory/mod.rs index a8557ccc..dedbea32 100644 --- a/tests/src/directory/mod.rs +++ b/tests/src/directory/mod.rs @@ -12,7 +12,6 @@ pub mod smtp; pub mod sql; use common::{Core, Server, config::smtp::session::AddressMapping}; -use compact_str::{CompactString, ToCompactString, format_compact}; use directory::{ Directories, Principal, Type, backend::internal::{PrincipalField, PrincipalSet, manage::ManageDirectory}, @@ -323,13 +322,13 @@ pub struct TestPrincipal { pub id: u32, pub typ: Type, pub quota: u64, - pub name: CompactString, - pub secrets: Vec, - pub emails: Vec, - pub member_of: Vec, - pub roles: Vec, - pub lists: Vec, - pub description: Option, + pub name: String, + pub secrets: Vec, + pub emails: Vec, + pub member_of: Vec, + pub roles: Vec, + pub lists: Vec, + pub description: Option, } impl DirectoryTest { @@ -547,21 +546,9 @@ impl From for TestPrincipal { id: value.id(), typ: value.typ(), quota: value.quota(), - member_of: value - .member_of() - .iter() - .map(|v| v.to_compact_string()) - .collect(), - roles: value - .roles() - .iter() - .map(|v| v.to_compact_string()) - .collect(), - lists: value - .lists() - .iter() - .map(|v| v.to_compact_string()) - .collect(), + member_of: value.member_of().iter().map(|v| v.to_string()).collect(), + roles: value.roles().iter().map(|v| v.to_string()).collect(), + lists: value.lists().iter().map(|v| v.to_string()).collect(), name: value.name, secrets: value.secrets, emails: value.emails, @@ -585,23 +572,23 @@ impl From for PrincipalSet { #[derive(Clone, PartialEq, Eq, Hash)] pub enum Item { - IsAccount(CompactString), + IsAccount(String), Authenticate(Credentials), - Verify(CompactString), - Expand(CompactString), + Verify(String), + Expand(String), } #[derive(Debug, Clone, PartialEq, Eq)] pub enum LookupResult { True, False, - Values(Vec), + Values(Vec), } impl Item { pub fn append(&self, append: usize) -> Self { match self { - Item::IsAccount(str) => Item::IsAccount(format_compact!("{append}{str}")), + Item::IsAccount(str) => Item::IsAccount(format!("{append}{str}")), Item::Authenticate(str) => Item::Authenticate(match str { Credentials::Plain { username, secret } => Credentials::Plain { username: username.to_string(), @@ -615,8 +602,8 @@ impl Item { secret: format!("{append}{secret}"), }, }), - Item::Verify(str) => Item::Verify(format_compact!("{append}{str}")), - Item::Expand(str) => Item::Expand(format_compact!("{append}{str}")), + Item::Verify(str) => Item::Verify(format!("{append}{str}")), + Item::Expand(str) => Item::Expand(format!("{append}{str}")), } } @@ -637,9 +624,9 @@ impl LookupResult { let mut r = Vec::with_capacity(v.len()); for (pos, val) in v.iter().enumerate() { r.push(if pos == 0 { - format_compact!("{append}{val}") + format!("{append}{val}") } else { - val.to_compact_string() + val.to_string() }); } LookupResult::Values(r) @@ -658,8 +645,8 @@ impl From for LookupResult { } } -impl From> for LookupResult { - fn from(v: Vec) -> Self { +impl From> for LookupResult { + fn from(v: Vec) -> Self { LookupResult::Values(v) } } diff --git a/tests/src/directory/smtp.rs b/tests/src/directory/smtp.rs index 483400c3..b8078b12 100644 --- a/tests/src/directory/smtp.rs +++ b/tests/src/directory/smtp.rs @@ -4,13 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::sync::Arc; - +use super::dummy_tls_acceptor; +use crate::directory::{DirectoryTest, Item, LookupResult}; use common::listener::limiter::{ConcurrencyLimiter, InFlight}; -use compact_str::ToCompactString; use directory::{QueryBy, backend::RcptType}; use mail_parser::decoders::base64::base64_decode; use mail_send::Credentials; +use std::sync::Arc; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpStream}, @@ -18,10 +18,6 @@ use tokio::{ }; use tokio_rustls::TlsAcceptor; -use crate::directory::{DirectoryTest, Item, LookupResult}; - -use super::dummy_tls_acceptor; - #[tokio::test] async fn lmtp_directory() { // Spawn mock LMTP server @@ -308,7 +304,7 @@ async fn accept_smtp( .split(',') .filter_map(|s| { if !s.is_empty() { - s.to_compact_string().into() + s.to_string().into() } else { None } diff --git a/tests/src/directory/sql.rs b/tests/src/directory/sql.rs index 45ed551a..380fdfb6 100644 --- a/tests/src/directory/sql.rs +++ b/tests/src/directory/sql.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use compact_str::{CompactString, ToCompactString}; use directory::{ QueryBy, ROLE_USER, Type, backend::{RcptType, internal::manage::ManageDirectory}, @@ -133,14 +132,14 @@ async fn sql_directory() { member_of: map_account_ids(base_store, vec!["sales"]) .await .into_iter() - .map(|v| v.to_compact_string()) + .map(|v| v.to_string()) .collect(), emails: vec![ "john@example.org".into(), "jdoe@example.org".into(), "john.doe@example.org".into() ], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -167,7 +166,7 @@ async fn sql_directory() { typ: Type::Individual, quota: 500000, emails: vec!["bill@example.org".into(),], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -190,7 +189,7 @@ async fn sql_directory() { description: Some("Administrator".into()), secrets: vec!["very_secret".into()], typ: Type::Individual, - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -225,10 +224,10 @@ async fn sql_directory() { member_of: map_account_ids(base_store, vec!["sales", "support"]) .await .into_iter() - .map(|v| v.to_compact_string()) + .map(|v| v.to_string()) .collect(), emails: vec!["jane@example.org".into(),], - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -246,7 +245,7 @@ async fn sql_directory() { name: "sales".into(), description: Some("Sales Team".into()), typ: Type::Group, - roles: vec![ROLE_USER.to_compact_string()], + roles: vec![ROLE_USER.to_string()], ..Default::default() } ); @@ -316,26 +315,26 @@ async fn sql_directory() { // VRFY assert_eq!( core.vrfy(&handle, "jane", 0).await.unwrap(), - vec!["jane@example.org".to_compact_string()] + vec!["jane@example.org".to_string()] ); assert_eq!( core.vrfy(&handle, "john", 0).await.unwrap(), vec![ - "john.doe@example.org".to_compact_string(), - "john@example.org".to_compact_string(), + "john.doe@example.org".to_string(), + "john@example.org".to_string(), ] ); assert_eq!( core.vrfy(&handle, "jane+alias@example", 0).await.unwrap(), - vec!["jane@example.org".to_compact_string()] + vec!["jane@example.org".to_string()] ); assert_eq!( core.vrfy(&handle, "info", 0).await.unwrap(), - Vec::::new() + Vec::::new() ); assert_eq!( core.vrfy(&handle, "invalid", 0).await.unwrap(), - Vec::::new() + Vec::::new() ); // EXPN (now handled by the internal store) diff --git a/tests/src/jmap/auth_oauth.rs b/tests/src/jmap/auth_oauth.rs index b73119b5..0d05d3a7 100644 --- a/tests/src/jmap/auth_oauth.rs +++ b/tests/src/jmap/auth_oauth.rs @@ -14,7 +14,7 @@ use common::auth::oauth::{ oidc::StandardClaims, registration::{ClientRegistrationRequest, ClientRegistrationResponse}, }; -use compact_str::ToCompactString; + use http::auth::oauth::{ DeviceAuthResponse, ErrorType, OAuthCodeRequest, TokenResponse, auth::OAuthMetadata, openid::OpenIdMetadata, @@ -82,7 +82,7 @@ pub async fn test(params: &mut JMAPTest) { &metadata.registration_endpoint, None, &ClientRegistrationRequest { - redirect_uris: vec!["https://localhost".to_compact_string()], + redirect_uris: vec!["https://localhost".to_string()], ..Default::default() }, ) @@ -165,7 +165,7 @@ pub async fn test(params: &mut JMAPTest) { let claims = id_token.payload().unwrap(); let registered_claims = &claims.registered; let private_claims = &claims.private; - assert_eq!(registered_claims.issuer, Some(oidc_metadata.issuer.into())); + assert_eq!(registered_claims.issuer, Some(oidc_metadata.issuer)); assert_eq!(registered_claims.subject, Some(john_int_id.to_string())); assert_eq!( registered_claims.audience, diff --git a/tests/src/jmap/permissions.rs b/tests/src/jmap/permissions.rs index 7636888b..e1ec0709 100644 --- a/tests/src/jmap/permissions.rs +++ b/tests/src/jmap/permissions.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use ahash::AHashSet; use common::auth::{AccessToken, TenantInfo}; -use compact_str::ToCompactString; + use directory::{ Permission, Type, backend::internal::{PrincipalField, PrincipalSet, PrincipalUpdate, PrincipalValue}, @@ -33,10 +33,10 @@ pub async fn test(params: &JMAPTest) { "/api/principal", &PrincipalSet::new(u32::MAX, Type::Individual) .with_field(PrincipalField::Name, "role_player") - .with_field(PrincipalField::Roles, vec!["user".to_compact_string()]) + .with_field(PrincipalField::Roles, vec!["user".to_string()]) .with_field( PrincipalField::DisabledPermissions, - vec![Permission::Pop3Dele.name().to_compact_string()], + vec![Permission::Pop3Dele.name().to_string()], ), ) .await @@ -81,19 +81,19 @@ pub async fn test(params: &JMAPTest) { api.post::( "/api/principal", &PrincipalSet::new(u32::MAX, Type::Role) - .with_field(PrincipalField::Name, role.to_compact_string()) + .with_field(PrincipalField::Name, role.to_string()) .with_field( PrincipalField::EnabledPermissions, permissions .iter() - .map(|p| p.name().to_compact_string()) + .map(|p| p.name().to_string()) .collect::>(), ) .with_field( PrincipalField::Roles, parent_role .iter() - .map(|r| r.to_compact_string()) + .map(|r| r.to_string()) .collect::>(), ), ) @@ -107,7 +107,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/email_user", &vec![PrincipalUpdate::add_item( PrincipalField::DisabledPermissions, - PrincipalValue::String(Permission::ManageEncryption.name().to_compact_string()), + PrincipalValue::String(Permission::ManageEncryption.name().to_string()), )], ) .await @@ -119,7 +119,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/role_player", &vec![PrincipalUpdate::set( PrincipalField::Roles, - PrincipalValue::StringList(vec!["email_user".to_compact_string()]), + PrincipalValue::StringList(vec!["email_user".to_string()]), )], ) .await @@ -250,10 +250,7 @@ pub async fn test(params: &JMAPTest) { .with_field(PrincipalField::Name, "foobar") .with_field( PrincipalField::Roles, - vec![ - "tenant-admin".to_compact_string(), - "user".to_compact_string(), - ], + vec!["tenant-admin".to_string(), "user".to_string()], ) .with_field( PrincipalField::Quota, @@ -270,10 +267,7 @@ pub async fn test(params: &JMAPTest) { .with_field(PrincipalField::Name, "xanadu") .with_field( PrincipalField::Roles, - vec![ - "tenant-admin".to_compact_string(), - "user".to_compact_string(), - ], + vec!["tenant-admin".to_string(), "user".to_string()], ), ) .await @@ -285,17 +279,14 @@ pub async fn test(params: &JMAPTest) { "/api/principal", &PrincipalSet::new(u32::MAX, Type::Individual) .with_field(PrincipalField::Name, "admin-foobar") - .with_field( - PrincipalField::Roles, - vec!["tenant-admin".to_compact_string()], - ) + .with_field(PrincipalField::Roles, vec!["tenant-admin".to_string()]) .with_field( PrincipalField::Secrets, - PrincipalValue::String("mytenantpass".to_compact_string()), + PrincipalValue::String("mytenantpass".to_string()), ) .with_field( PrincipalField::Tenant, - PrincipalValue::String("foobar".to_compact_string()), + PrincipalValue::String("foobar".to_string()), ), ) .await @@ -309,7 +300,7 @@ pub async fn test(params: &JMAPTest) { .with_field(PrincipalField::Name, "foobar.org") .with_field( PrincipalField::Tenant, - PrincipalValue::String("foobar".to_compact_string()), + PrincipalValue::String("foobar".to_string()), ), ) .await @@ -329,17 +320,14 @@ pub async fn test(params: &JMAPTest) { "/api/principal", &PrincipalSet::new(u32::MAX, Type::Individual) .with_field(PrincipalField::Name, "admin@foobar.org") - .with_field( - PrincipalField::Roles, - vec!["tenant-admin".to_compact_string()], - ) + .with_field(PrincipalField::Roles, vec!["tenant-admin".to_string()]) .with_field( PrincipalField::Secrets, - PrincipalValue::String("mytenantpass".to_compact_string()), + PrincipalValue::String("mytenantpass".to_string()), ) .with_field( PrincipalField::Tenant, - PrincipalValue::String("foobar".to_compact_string()), + PrincipalValue::String("foobar".to_string()), ), ) .await @@ -372,7 +360,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/foobar", &vec![PrincipalUpdate::set( PrincipalField::Tenant, - PrincipalValue::String("subfoobar".to_compact_string()), + PrincipalValue::String("subfoobar".to_string()), )], ) .await @@ -417,11 +405,8 @@ pub async fn test(params: &JMAPTest) { .post::( "/api/principal", &PrincipalSet::new(u32::MAX, Type::Individual) - .with_field(PrincipalField::Name, user.to_compact_string()) - .with_field( - PrincipalField::Roles, - vec!["tenant-admin".to_compact_string()], - ), + .with_field(PrincipalField::Name, user.to_string()) + .with_field(PrincipalField::Roles, vec!["tenant-admin".to_string()]), ) .await .unwrap() @@ -436,18 +421,15 @@ pub async fn test(params: &JMAPTest) { .with_field(PrincipalField::Name, "john@foobar.org") .with_field( PrincipalField::Roles, - vec![ - "tenant-admin".to_compact_string(), - "user".to_compact_string(), - ], + vec!["tenant-admin".to_string(), "user".to_string()], ) .with_field( PrincipalField::Secrets, - PrincipalValue::String("tenantpass".to_compact_string()), + PrincipalValue::String("tenantpass".to_string()), ) .with_field( PrincipalField::Tenant, - PrincipalValue::String("xanadu".to_compact_string()), + PrincipalValue::String("xanadu".to_string()), ), ) .await @@ -470,10 +452,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal", &PrincipalSet::new(u32::MAX, Type::Individual) .with_field(PrincipalField::Name, "jane@foobar.org") - .with_field( - PrincipalField::Roles, - vec!["tenant-admin".to_compact_string()], - ), + .with_field(PrincipalField::Roles, vec!["tenant-admin".to_string()]), ) .await .unwrap() @@ -487,7 +466,7 @@ pub async fn test(params: &JMAPTest) { .with_field(PrincipalField::Name, "no-mail-for-you@foobar.com") .with_field( PrincipalField::DisabledPermissions, - vec![Permission::EmailReceive.name().to_compact_string()], + vec![Permission::EmailReceive.name().to_string()], ), ) .await @@ -500,7 +479,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john@foobar.org", &vec![PrincipalUpdate::add_item( PrincipalField::Roles, - PrincipalValue::String("imap_user".to_compact_string()), + PrincipalValue::String("imap_user".to_string()), )], ) .await @@ -513,7 +492,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john@foobar.org", &vec![PrincipalUpdate::add_item( PrincipalField::Roles, - PrincipalValue::String("no-mail-for-you@foobar.com".to_compact_string()), + PrincipalValue::String("no-mail-for-you@foobar.com".to_string()), )], ) .await @@ -536,7 +515,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john@foobar.org", &vec![PrincipalUpdate::set( PrincipalField::Tenant, - PrincipalValue::String("xanadu".to_compact_string()), + PrincipalValue::String("xanadu".to_string()), )], ) .await @@ -550,7 +529,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john@foobar.org", &vec![PrincipalUpdate::set( PrincipalField::Name, - PrincipalValue::String(user.to_compact_string()), + PrincipalValue::String(user.to_string()), )], ) .await @@ -565,11 +544,11 @@ pub async fn test(params: &JMAPTest) { &vec![ PrincipalUpdate::set( PrincipalField::Name, - PrincipalValue::String("john.doe@foobar.org".to_compact_string()), + PrincipalValue::String("john.doe@foobar.org".to_string()), ), PrincipalUpdate::add_item( PrincipalField::Emails, - PrincipalValue::String("john@foobar.org".to_compact_string()), + PrincipalValue::String("john@foobar.org".to_string()), ), ], ) @@ -631,8 +610,8 @@ pub async fn test(params: &JMAPTest) { assert_eq!( server .deliver_message(IngestMessage { - sender_address: "bill@foobar.org".to_compact_string(), - recipients: vec!["john@foobar.org".to_compact_string()], + sender_address: "bill@foobar.org".to_string(), + recipients: vec!["john@foobar.org".to_string()], message_blob: message_blob.clone(), message_size: TEST_MESSAGE.len() as u64, session_id: 0, @@ -651,7 +630,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john.doe@foobar.org", &vec![PrincipalUpdate::remove_item( PrincipalField::Roles, - PrincipalValue::String("no-mail-for-you@foobar.com".to_compact_string()), + PrincipalValue::String("no-mail-for-you@foobar.com".to_string()), )], ) .await @@ -669,8 +648,8 @@ pub async fn test(params: &JMAPTest) { assert_eq!( server .deliver_message(IngestMessage { - sender_address: "bill@foobar.org".to_compact_string(), - recipients: vec!["john@foobar.org".to_compact_string()], + sender_address: "bill@foobar.org".to_string(), + recipients: vec!["john@foobar.org".to_string()], message_blob: message_blob.clone(), message_size: TEST_MESSAGE.len() as u64, session_id: 0, @@ -694,8 +673,8 @@ pub async fn test(params: &JMAPTest) { assert_eq!( server .deliver_message(IngestMessage { - sender_address: "bill@foobar.org".to_compact_string(), - recipients: vec!["john@foobar.org".to_compact_string()], + sender_address: "bill@foobar.org".to_string(), + recipients: vec!["john@foobar.org".to_string()], message_blob, message_size: TEST_MESSAGE.len() as u64, session_id: 0, @@ -712,7 +691,7 @@ pub async fn test(params: &JMAPTest) { "/api/principal/john.doe@foobar.org", &vec![PrincipalUpdate::set( PrincipalField::Tenant, - PrincipalValue::String("xanadu".to_compact_string()), + PrincipalValue::String("xanadu".to_string()), )], ) .await diff --git a/tests/src/smtp/config.rs b/tests/src/smtp/config.rs index 8961ccce..3abe59c7 100644 --- a/tests/src/smtp/config.rs +++ b/tests/src/smtp/config.rs @@ -14,7 +14,8 @@ use common::{ }, expr::{functions::ResolveVariable, if_block::*, tokenizer::TokenMap, *}, }; -use compact_str::{CompactString, ToCompactString}; + +use compact_str::ToCompactString; use throttle::parse_queue_rate_limiter; use tokio::net::TcpSocket; @@ -430,7 +431,7 @@ async fn eval_if() { assert_eq!( core.eval_if::( &IfBlock { - key: key.to_compact_string(), + key: key.to_string(), if_then: vec![IfThen { expr: Expression::try_parse(&mut config, key.as_str(), &token_map).unwrap(), then: Expression::from(true), @@ -487,12 +488,10 @@ async fn eval_dynvalue() { .unwrap(); let expected = config .property_require::>(("eval", test_name.as_str(), "expect")) - .unwrap_or_else(|| panic!("Missing expect for test {test_name:?}")) - .map(Into::into); + .unwrap_or_else(|| panic!("Missing expect for test {test_name:?}")); assert_eq!( - core.eval_if::(&if_block, &envelope, 0) - .await, + core.eval_if::(&if_block, &envelope, 0).await, expected, "failed for test {test_name:?}" ); diff --git a/tests/src/smtp/inbound/antispam.rs b/tests/src/smtp/inbound/antispam.rs index 134c049f..2621caf6 100644 --- a/tests/src/smtp/inbound/antispam.rs +++ b/tests/src/smtp/inbound/antispam.rs @@ -18,6 +18,7 @@ use common::{ }, }, }; + use compact_str::{CompactString, ToCompactString}; use http_proto::{JsonResponse, ToHttpResponse}; use hyper::Method; @@ -377,15 +378,15 @@ async fn antispam() { let value = value.trim(); match param { "remote_ip" => { - session.data.remote_ip_str = value.to_compact_string(); + session.data.remote_ip_str = value.to_string(); session.data.remote_ip = value.parse().unwrap(); } "helo_domain" => { - session.data.helo_domain = value.to_compact_string(); + session.data.helo_domain = value.to_string(); } "authenticated_as" => { session.data.authenticated_as = Some(Arc::new(AccessToken { - name: value.to_compact_string(), + name: value.to_string(), ..Default::default() })); } @@ -429,14 +430,13 @@ async fn antispam() { .collect(); } "envelope_from" => { - session.data.mail_from = - Some(SessionAddress::new(value.to_compact_string())); + session.data.mail_from = Some(SessionAddress::new(value.to_string())); } "envelope_to" => { session .data .rcpt_to - .push(SessionAddress::new(value.to_compact_string())); + .push(SessionAddress::new(value.to_string())); } "iprev.ptr" => { session @@ -506,7 +506,7 @@ async fn antispam() { session .data .mail_from - .get_or_insert_with(|| SessionAddress::new("".to_compact_string())) + .get_or_insert_with(|| SessionAddress::new("".to_string())) .flags = body_params; } diff --git a/tests/src/smtp/inbound/milter.rs b/tests/src/smtp/inbound/milter.rs index ffe5b8f9..331e3d7a 100644 --- a/tests/src/smtp/inbound/milter.rs +++ b/tests/src/smtp/inbound/milter.rs @@ -13,7 +13,7 @@ use common::{ expr::if_block::IfBlock, manager::webadmin::Resource, }; -use compact_str::CompactString; + use http_proto::{ToHttpResponse, request::fetch_body}; use hyper::{body, server::conn::http1, service::service_fn}; use hyper_util::rt::TokioIo; @@ -941,7 +941,7 @@ fn handle_mta_hook(request: Request, tests: Arc>) -> hooks::Resp } } Modification::ReplaceBody { value } => hooks::Modification::ReplaceContents { - value: CompactString::from_utf8(value.clone()).unwrap(), + value: String::from_utf8(value.clone()).unwrap(), }, Modification::AddHeader { name, value } => hooks::Modification::AddHeader { name: name.clone(), diff --git a/tests/src/smtp/lookup/sql.rs b/tests/src/smtp/lookup/sql.rs index 63e5891d..e94bbef2 100644 --- a/tests/src/smtp/lookup/sql.rs +++ b/tests/src/smtp/lookup/sql.rs @@ -11,7 +11,7 @@ use common::{ expr::{tokenizer::TokenMap, *}, }; -use compact_str::{CompactString, ToCompactString}; + use directory::{ QueryBy, Type, backend::internal::{PrincipalField, PrincipalSet, PrincipalValue, manage::ManageDirectory}, @@ -175,7 +175,7 @@ async fn lookup_sql() { .with_field(PrincipalField::Emails, "support@foobar.org") .with_field( PrincipalField::ExternalMembers, - PrincipalValue::StringList(vec!["mike@foobar.net".to_compact_string()]), + PrincipalValue::StringList(vec!["mike@foobar.net".to_string()]), ), None, None, @@ -190,9 +190,9 @@ async fn lookup_sql() { .with_field( PrincipalField::ExternalMembers, PrincipalValue::StringList(vec![ - "jane@foobar.org".to_compact_string(), - "john@foobar.org".to_compact_string(), - "bill@foobar.org".to_compact_string(), + "jane@foobar.org".to_string(), + "john@foobar.org".to_string(), + "bill@foobar.org".to_string(), ]), ), None, @@ -220,7 +220,7 @@ async fn lookup_sql() { Expression::try_parse(&mut config, ("test", test_name, "expr"), &token_map).unwrap(); assert_eq!( test.server - .eval_expr::(&e, &RecipientDomain::new("test.org"), "text", 0) + .eval_expr::(&e, &RecipientDomain::new("test.org"), "text", 0) .await .unwrap(), config.value(("test", test_name, "expect")).unwrap(), diff --git a/tests/src/smtp/outbound/dane.rs b/tests/src/smtp/outbound/dane.rs index 28dc1b7d..836bb593 100644 --- a/tests/src/smtp/outbound/dane.rs +++ b/tests/src/smtp/outbound/dane.rs @@ -343,7 +343,7 @@ async fn dane_test() { assert_eq!( tlsa.verify(0, &host, Some(&certs)), Err(Status::PermanentFailure(Error::DaneError(ErrorDetails { - entity: host.into(), + entity: host, details: "No matching certificates found in TLSA records".into() }))) );