Zero copy everything

This commit is contained in:
mdecimus
2025-02-27 16:23:34 +01:00
parent 2826ff1548
commit 84be252413
86 changed files with 3749 additions and 2187 deletions

View File

@@ -6,19 +6,16 @@
use std::borrow::Borrow;
use store::{
write::{DeserializeFrom, SerializeInto},
BlobClass,
};
use store::BlobClass;
use utils::{
BlobHash,
codec::{
base32_custom::{Base32Reader, Base32Writer},
leb128::{Leb128Iterator, Leb128Writer},
},
BlobHash,
};
use crate::parser::{base32::JsonBase32Reader, json::Parser, JsonObjectParser};
use crate::parser::{JsonObjectParser, base32::JsonBase32Reader, json::Parser};
const B_LINKED: u8 = 0x10;
const B_RESERVED: u8 = 0x20;
@@ -199,15 +196,3 @@ impl std::fmt::Display for BlobId {
f.write_str(&writer.finalize())
}
}
impl SerializeInto for BlobId {
fn serialize_into(&self, buf: &mut Vec<u8>) {
self.serialize_as(buf)
}
}
impl DeserializeFrom for BlobId {
fn deserialize_from(bytes: &mut std::slice::Iter<'_, u8>) -> Option<Self> {
BlobId::from_iter(bytes)
}
}

View File

@@ -8,9 +8,8 @@ use std::fmt::Display;
use store::{
Serialize,
write::{DeserializeFrom, MaybeDynamicId, SerializeInto, TagValue},
write::{MaybeDynamicId, TagValue},
};
use utils::codec::leb128::{Leb128Iterator, Leb128Vec};
use crate::parser::{JsonObjectParser, json::Parser};
@@ -28,8 +27,19 @@ pub const FORWARDED: usize = 10;
pub const MDN_SENT: usize = 11;
pub const OTHER: usize = 12;
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
#[derive(
rkyv::Serialize,
rkyv::Deserialize,
rkyv::Archive,
Debug,
Clone,
PartialEq,
Eq,
Hash,
serde::Serialize,
)]
#[serde(untagged)]
#[rkyv(derive(PartialEq))]
pub enum Keyword {
#[serde(rename(serialize = "$seen"))]
Seen,
@@ -168,6 +178,26 @@ impl Display for Keyword {
}
}
impl Display for ArchivedKeyword {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ArchivedKeyword::Seen => write!(f, "$seen"),
ArchivedKeyword::Draft => write!(f, "$draft"),
ArchivedKeyword::Flagged => write!(f, "$flagged"),
ArchivedKeyword::Answered => write!(f, "$answered"),
ArchivedKeyword::Recent => write!(f, "$recent"),
ArchivedKeyword::Important => write!(f, "$important"),
ArchivedKeyword::Phishing => write!(f, "$phishing"),
ArchivedKeyword::Junk => write!(f, "$junk"),
ArchivedKeyword::NotJunk => write!(f, "$notjunk"),
ArchivedKeyword::Deleted => write!(f, "$deleted"),
ArchivedKeyword::Forwarded => write!(f, "$forwarded"),
ArchivedKeyword::MdnSent => write!(f, "$mdnsent"),
ArchivedKeyword::Other(s) => write!(f, "{}", s),
}
}
}
impl Serialize for Keyword {
fn serialize(&self) -> trc::Result<Vec<u8>> {
Ok(match self {
@@ -188,58 +218,6 @@ impl Serialize for Keyword {
}
}
impl SerializeInto for Keyword {
fn serialize_into(&self, buf: &mut Vec<u8>) {
match self {
Keyword::Seen => buf.push(SEEN as u8),
Keyword::Draft => buf.push(DRAFT as u8),
Keyword::Flagged => buf.push(FLAGGED as u8),
Keyword::Answered => buf.push(ANSWERED as u8),
Keyword::Recent => buf.push(RECENT as u8),
Keyword::Important => buf.push(IMPORTANT as u8),
Keyword::Phishing => buf.push(PHISHING as u8),
Keyword::Junk => buf.push(JUNK as u8),
Keyword::NotJunk => buf.push(NOTJUNK as u8),
Keyword::Deleted => buf.push(DELETED as u8),
Keyword::Forwarded => buf.push(FORWARDED as u8),
Keyword::MdnSent => buf.push(MDN_SENT as u8),
Keyword::Other(string) => {
buf.push_leb128(OTHER + string.len());
if !string.is_empty() {
buf.extend_from_slice(string.as_bytes())
}
}
}
}
}
impl DeserializeFrom for Keyword {
fn deserialize_from(bytes: &mut std::slice::Iter<'_, u8>) -> Option<Self> {
match bytes.next_leb128::<usize>()? {
SEEN => Some(Keyword::Seen),
DRAFT => Some(Keyword::Draft),
FLAGGED => Some(Keyword::Flagged),
ANSWERED => Some(Keyword::Answered),
RECENT => Some(Keyword::Recent),
IMPORTANT => Some(Keyword::Important),
PHISHING => Some(Keyword::Phishing),
JUNK => Some(Keyword::Junk),
NOTJUNK => Some(Keyword::NotJunk),
DELETED => Some(Keyword::Deleted),
FORWARDED => Some(Keyword::Forwarded),
MDN_SENT => Some(Keyword::MdnSent),
other => {
let len = other - OTHER;
let mut keyword = Vec::with_capacity(len);
for _ in 0..len {
keyword.push(*bytes.next()?);
}
Some(Keyword::Other(String::from_utf8(keyword).ok()?))
}
}
}
}
impl Keyword {
pub fn id(&self) -> Result<u32, String> {
match self {
@@ -278,6 +256,26 @@ impl Keyword {
}
}
impl ArchivedKeyword {
pub fn id(&self) -> Result<u32, String> {
match self {
ArchivedKeyword::Seen => Ok(SEEN as u32),
ArchivedKeyword::Draft => Ok(DRAFT as u32),
ArchivedKeyword::Flagged => Ok(FLAGGED as u32),
ArchivedKeyword::Answered => Ok(ANSWERED as u32),
ArchivedKeyword::Recent => Ok(RECENT as u32),
ArchivedKeyword::Important => Ok(IMPORTANT as u32),
ArchivedKeyword::Phishing => Ok(PHISHING as u32),
ArchivedKeyword::Junk => Ok(JUNK as u32),
ArchivedKeyword::NotJunk => Ok(NOTJUNK as u32),
ArchivedKeyword::Deleted => Ok(DELETED as u32),
ArchivedKeyword::Forwarded => Ok(FORWARDED as u32),
ArchivedKeyword::MdnSent => Ok(MDN_SENT as u32),
ArchivedKeyword::Other(string) => Err(string.to_string()),
}
}
}
impl From<Keyword> for TagValue<u32> {
fn from(value: Keyword) -> Self {
match value.into_id() {
@@ -313,3 +311,12 @@ impl From<&Keyword> for TagValue<MaybeDynamicId> {
}
}
}
impl From<&ArchivedKeyword> for TagValue<MaybeDynamicId> {
fn from(value: &ArchivedKeyword) -> Self {
match value.id() {
Ok(id) => TagValue::Id(MaybeDynamicId::Static(id)),
Err(string) => TagValue::Text(string.into_bytes()),
}
}
}

View File

@@ -8,7 +8,7 @@ use std::fmt::{Display, Formatter};
use mail_parser::HeaderName;
use serde::Serialize;
use store::write::{DeserializeFrom, SerializeInto, ValueClass};
use store::write::ValueClass;
use crate::parser::{JsonObjectParser, json::Parser};
@@ -1211,240 +1211,6 @@ impl Property {
}
}
impl SerializeInto for Property {
fn serialize_into(&self, buf: &mut Vec<u8>) {
buf.push(match self {
Property::IsActive => 0,
Property::IsEnabled => 1,
Property::IsSubscribed => 2,
Property::Keys => 3,
Property::Keywords => 4,
Property::Language => 5,
Property::Location => 6,
Property::MailboxIds => 7,
Property::MayDelete => 8,
Property::MdnBlobIds => 9,
Property::Members => 10,
Property::MessageId => 11,
Property::MyRights => 12,
Property::Name => 13,
Property::ParentId => 14,
Property::PartId => 15,
Property::Picture => 16,
Property::Preview => 17,
Property::Quota => 18,
Property::ReceivedAt => 19,
Property::References => 20,
Property::ReplyTo => 21,
Property::Role => 22,
Property::Secret => 23,
Property::SendAt => 24,
Property::Sender => 25,
Property::SentAt => 26,
Property::Size => 27,
Property::SortOrder => 28,
Property::Subject => 29,
Property::SubParts => 30,
Property::TextBody => 31,
Property::TextSignature => 32,
Property::ThreadId => 33,
Property::Timezone => 34,
Property::To => 35,
Property::ToDate => 36,
Property::TotalEmails => 37,
Property::TotalThreads => 38,
Property::Type => 39,
Property::Types => 40,
Property::UndoStatus => 41,
Property::UnreadEmails => 42,
Property::UnreadThreads => 43,
Property::Url => 44,
Property::VerificationCode => 45,
Property::Parameters => 46,
Property::Addresses => 47,
Property::P256dh => 48,
Property::Auth => 49,
Property::Value => 50,
Property::SmtpReply => 51,
Property::Delivered => 52,
Property::Displayed => 53,
Property::MailFrom => 54,
Property::RcptTo => 55,
Property::IsEncodingProblem => 56,
Property::IsTruncated => 57,
Property::MayReadItems => 58,
Property::MayAddItems => 59,
Property::MayRemoveItems => 60,
Property::MaySetSeen => 61,
Property::MaySetKeywords => 62,
Property::MayCreateChild => 63,
Property::MayRename => 64,
Property::MaySubmit => 65,
Property::Acl => 66,
Property::Aliases => 67,
Property::Attachments => 68,
Property::Bcc => 69,
Property::BlobId => 70,
Property::BodyStructure => 71,
Property::BodyValues => 72,
Property::Capabilities => 73,
Property::Cc => 74,
Property::Charset => 75,
Property::Cid => 76,
Property::DeliveryStatus => 77,
Property::Description => 78,
Property::DeviceClientId => 79,
Property::Disposition => 80,
Property::DsnBlobIds => 81,
Property::Email => 82,
Property::EmailId => 83,
Property::EmailIds => 84,
Property::Envelope => 85,
Property::Expires => 86,
Property::From => 87,
Property::FromDate => 88,
Property::HasAttachment => 89,
Property::Header(_) => 90,
Property::Headers => 91,
Property::HtmlBody => 92,
Property::HtmlSignature => 93,
Property::Id => 94,
Property::IdentityId => 95,
Property::InReplyTo => 96,
Property::_T(value) => {
buf.push(97);
value.serialize_into(buf);
return;
}
Property::ResourceType => 98,
Property::Used => 99,
Property::HardLimit => 100,
Property::WarnLimit => 101,
Property::SoftLimit => 102,
Property::Scope => 103,
Property::Digest(_) | Property::Data(_) => {
unreachable!("Property::Digest and Property::Data are not serializable")
}
});
}
}
impl DeserializeFrom for Property {
fn deserialize_from(bytes: &mut std::slice::Iter<'_, u8>) -> Option<Self> {
match *bytes.next()? {
0 => Some(Property::IsActive),
1 => Some(Property::IsEnabled),
2 => Some(Property::IsSubscribed),
3 => Some(Property::Keys),
4 => Some(Property::Keywords),
5 => Some(Property::Language),
6 => Some(Property::Location),
7 => Some(Property::MailboxIds),
8 => Some(Property::MayDelete),
9 => Some(Property::MdnBlobIds),
10 => Some(Property::Members),
11 => Some(Property::MessageId),
12 => Some(Property::MyRights),
13 => Some(Property::Name),
14 => Some(Property::ParentId),
15 => Some(Property::PartId),
16 => Some(Property::Picture),
17 => Some(Property::Preview),
18 => Some(Property::Quota),
19 => Some(Property::ReceivedAt),
20 => Some(Property::References),
21 => Some(Property::ReplyTo),
22 => Some(Property::Role),
23 => Some(Property::Secret),
24 => Some(Property::SendAt),
25 => Some(Property::Sender),
26 => Some(Property::SentAt),
27 => Some(Property::Size),
28 => Some(Property::SortOrder),
29 => Some(Property::Subject),
30 => Some(Property::SubParts),
31 => Some(Property::TextBody),
32 => Some(Property::TextSignature),
33 => Some(Property::ThreadId),
34 => Some(Property::Timezone),
35 => Some(Property::To),
36 => Some(Property::ToDate),
37 => Some(Property::TotalEmails),
38 => Some(Property::TotalThreads),
39 => Some(Property::Type),
40 => Some(Property::Types),
41 => Some(Property::UndoStatus),
42 => Some(Property::UnreadEmails),
43 => Some(Property::UnreadThreads),
44 => Some(Property::Url),
45 => Some(Property::VerificationCode),
46 => Some(Property::Parameters),
47 => Some(Property::Addresses),
48 => Some(Property::P256dh),
49 => Some(Property::Auth),
50 => Some(Property::Value),
51 => Some(Property::SmtpReply),
52 => Some(Property::Delivered),
53 => Some(Property::Displayed),
54 => Some(Property::MailFrom),
55 => Some(Property::RcptTo),
56 => Some(Property::IsEncodingProblem),
57 => Some(Property::IsTruncated),
58 => Some(Property::MayReadItems),
59 => Some(Property::MayAddItems),
60 => Some(Property::MayRemoveItems),
61 => Some(Property::MaySetSeen),
62 => Some(Property::MaySetKeywords),
63 => Some(Property::MayCreateChild),
64 => Some(Property::MayRename),
65 => Some(Property::MaySubmit),
66 => Some(Property::Acl),
67 => Some(Property::Aliases),
68 => Some(Property::Attachments),
69 => Some(Property::Bcc),
70 => Some(Property::BlobId),
71 => Some(Property::BodyStructure),
72 => Some(Property::BodyValues),
73 => Some(Property::Capabilities),
74 => Some(Property::Cc),
75 => Some(Property::Charset),
76 => Some(Property::Cid),
77 => Some(Property::DeliveryStatus),
78 => Some(Property::Description),
79 => Some(Property::DeviceClientId),
80 => Some(Property::Disposition),
81 => Some(Property::DsnBlobIds),
82 => Some(Property::Email),
83 => Some(Property::EmailId),
84 => Some(Property::EmailIds),
85 => Some(Property::Envelope),
86 => Some(Property::Expires),
87 => Some(Property::From),
88 => Some(Property::FromDate),
89 => Some(Property::HasAttachment),
90 => Some(Property::Header(HeaderProperty {
form: HeaderForm::Raw,
header: String::new(),
all: false,
})), // Never serialized
91 => Some(Property::Headers),
92 => Some(Property::HtmlBody),
93 => Some(Property::HtmlSignature),
94 => Some(Property::Id),
95 => Some(Property::IdentityId),
96 => Some(Property::InReplyTo),
97 => String::deserialize_from(bytes).map(Property::_T),
98 => Some(Property::ResourceType),
99 => Some(Property::Used),
100 => Some(Property::HardLimit),
101 => Some(Property::WarnLimit),
102 => Some(Property::SoftLimit),
103 => Some(Property::Scope),
_ => None,
}
}
}
impl Serialize for Property {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View File

@@ -7,7 +7,6 @@
use std::fmt::Display;
use serde::Serialize;
use store::write::{DeserializeFrom, SerializeInto};
use utils::map::bitmap::BitmapItem;
use crate::parser::{JsonObjectParser, json::Parser};
@@ -206,33 +205,6 @@ impl Display for DataType {
}
}
impl SerializeInto for DataType {
fn serialize_into(&self, buf: &mut Vec<u8>) {
buf.push(*self as u8);
}
}
impl DeserializeFrom for DataType {
fn deserialize_from(bytes: &mut std::slice::Iter<'_, u8>) -> Option<Self> {
match *bytes.next()? {
0 => Some(DataType::Email),
1 => Some(DataType::EmailDelivery),
2 => Some(DataType::EmailSubmission),
3 => Some(DataType::Mailbox),
4 => Some(DataType::Thread),
5 => Some(DataType::Identity),
6 => Some(DataType::Core),
7 => Some(DataType::PushSubscription),
8 => Some(DataType::SearchSnippet),
9 => Some(DataType::VacationResponse),
10 => Some(DataType::Mdn),
11 => Some(DataType::Quota),
12 => Some(DataType::SieveScript),
_ => None,
}
}
}
impl<'de> serde::Deserialize<'de> for DataType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where