use std::borrow::Cow;
use std::collections::HashMap;
use std::ops::RangeInclusive;
pub mod acls;
pub use acls::*;
fn to_owned_cow<T: ?Sized + ToOwned>(c: Cow<'_, T>) -> Cow<'static, T> {
Cow::Owned(c.into_owned())
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request<'a>(pub Cow<'a, [u8]>, pub Cow<'a, [u8]>);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
All,
Fast,
Full,
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Response<'a> {
Capabilities(Vec<Capability<'a>>),
Continue {
code: Option<ResponseCode<'a>>,
information: Option<Cow<'a, str>>,
},
Done {
tag: RequestId,
status: Status,
code: Option<ResponseCode<'a>>,
information: Option<Cow<'a, str>>,
},
Data {
status: Status,
code: Option<ResponseCode<'a>>,
information: Option<Cow<'a, str>>,
},
Expunge(u32),
Vanished {
earlier: bool,
uids: Vec<std::ops::RangeInclusive<u32>>,
},
Fetch(u32, Vec<AttributeValue<'a>>),
MailboxData(MailboxDatum<'a>),
Quota(Quota<'a>),
QuotaRoot(QuotaRoot<'a>),
Id(Option<HashMap<Cow<'a, str>, Cow<'a, str>>>),
Acl(Acl<'a>),
ListRights(ListRights<'a>),
MyRights(MyRights<'a>),
}
impl<'a> Response<'a> {
pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult<'a> {
crate::parser::parse_response(buf)
}
pub fn into_owned(self) -> Response<'static> {
match self {
Response::Capabilities(capabilities) => Response::Capabilities(
capabilities
.into_iter()
.map(Capability::into_owned)
.collect(),
),
Response::Continue { code, information } => Response::Continue {
code: code.map(ResponseCode::into_owned),
information: information.map(to_owned_cow),
},
Response::Done {
tag,
status,
code,
information,
} => Response::Done {
tag,
status,
code: code.map(ResponseCode::into_owned),
information: information.map(to_owned_cow),
},
Response::Data {
status,
code,
information,
} => Response::Data {
status,
code: code.map(ResponseCode::into_owned),
information: information.map(to_owned_cow),
},
Response::Expunge(seq) => Response::Expunge(seq),
Response::Vanished { earlier, uids } => Response::Vanished { earlier, uids },
Response::Fetch(seq, attrs) => Response::Fetch(
seq,
attrs.into_iter().map(AttributeValue::into_owned).collect(),
),
Response::MailboxData(datum) => Response::MailboxData(datum.into_owned()),
Response::Quota(quota) => Response::Quota(quota.into_owned()),
Response::QuotaRoot(quota_root) => Response::QuotaRoot(quota_root.into_owned()),
Response::Id(map) => Response::Id(map.map(|m| {
m.into_iter()
.map(|(k, v)| (to_owned_cow(k), to_owned_cow(v)))
.collect()
})),
Response::Acl(acl_list) => Response::Acl(acl_list.into_owned()),
Response::ListRights(rights) => Response::ListRights(rights.into_owned()),
Response::MyRights(rights) => Response::MyRights(rights.into_owned()),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum Status {
Ok,
No,
Bad,
PreAuth,
Bye,
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ResponseCode<'a> {
Alert,
BadCharset(Option<Vec<Cow<'a, str>>>),
Capabilities(Vec<Capability<'a>>),
HighestModSeq(u64), Parse,
PermanentFlags(Vec<Cow<'a, str>>),
ReadOnly,
ReadWrite,
TryCreate,
UidNext(u32),
UidValidity(u32),
Unseen(u32),
AppendUid(u32, Vec<UidSetMember>),
CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
UidNotSticky,
MetadataLongEntries(u64), MetadataMaxSize(u64), MetadataTooMany, MetadataNoPrivate, }
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum UidSetMember {
UidRange(RangeInclusive<u32>),
Uid(u32),
}
impl From<RangeInclusive<u32>> for UidSetMember {
fn from(x: RangeInclusive<u32>) -> Self {
UidSetMember::UidRange(x)
}
}
impl From<u32> for UidSetMember {
fn from(x: u32) -> Self {
UidSetMember::Uid(x)
}
}
impl<'a> ResponseCode<'a> {
pub fn into_owned(self) -> ResponseCode<'static> {
match self {
ResponseCode::Alert => ResponseCode::Alert,
ResponseCode::BadCharset(v) => {
ResponseCode::BadCharset(v.map(|vs| vs.into_iter().map(to_owned_cow).collect()))
}
ResponseCode::Capabilities(v) => {
ResponseCode::Capabilities(v.into_iter().map(Capability::into_owned).collect())
}
ResponseCode::HighestModSeq(v) => ResponseCode::HighestModSeq(v),
ResponseCode::Parse => ResponseCode::Parse,
ResponseCode::PermanentFlags(v) => {
ResponseCode::PermanentFlags(v.into_iter().map(to_owned_cow).collect())
}
ResponseCode::ReadOnly => ResponseCode::ReadOnly,
ResponseCode::ReadWrite => ResponseCode::ReadWrite,
ResponseCode::TryCreate => ResponseCode::TryCreate,
ResponseCode::UidNext(v) => ResponseCode::UidNext(v),
ResponseCode::UidValidity(v) => ResponseCode::UidValidity(v),
ResponseCode::Unseen(v) => ResponseCode::Unseen(v),
ResponseCode::AppendUid(a, b) => ResponseCode::AppendUid(a, b),
ResponseCode::CopyUid(a, b, c) => ResponseCode::CopyUid(a, b, c),
ResponseCode::UidNotSticky => ResponseCode::UidNotSticky,
ResponseCode::MetadataLongEntries(v) => ResponseCode::MetadataLongEntries(v),
ResponseCode::MetadataMaxSize(v) => ResponseCode::MetadataMaxSize(v),
ResponseCode::MetadataTooMany => ResponseCode::MetadataTooMany,
ResponseCode::MetadataNoPrivate => ResponseCode::MetadataNoPrivate,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
#[non_exhaustive]
pub enum StatusAttribute {
HighestModSeq(u64), Messages(u32),
Recent(u32),
UidNext(u32),
UidValidity(u32),
Unseen(u32),
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
pub entry: String,
pub value: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone)]
#[non_exhaustive]
pub enum MailboxDatum<'a> {
Exists(u32),
Flags(Vec<Cow<'a, str>>),
List {
name_attributes: Vec<NameAttribute<'a>>,
delimiter: Option<Cow<'a, str>>,
name: Cow<'a, str>,
},
Search(Vec<u32>),
Sort(Vec<u32>),
Status {
mailbox: Cow<'a, str>,
status: Vec<StatusAttribute>,
},
Recent(u32),
MetadataSolicited {
mailbox: Cow<'a, str>,
values: Vec<Metadata>,
},
MetadataUnsolicited {
mailbox: Cow<'a, str>,
values: Vec<Cow<'a, str>>,
},
GmailLabels(Vec<Cow<'a, str>>),
GmailMsgId(u64),
}
impl<'a> MailboxDatum<'a> {
pub fn into_owned(self) -> MailboxDatum<'static> {
match self {
MailboxDatum::Exists(seq) => MailboxDatum::Exists(seq),
MailboxDatum::Flags(flags) => {
MailboxDatum::Flags(flags.into_iter().map(to_owned_cow).collect())
}
MailboxDatum::List {
name_attributes,
delimiter,
name,
} => MailboxDatum::List {
name_attributes: name_attributes
.into_iter()
.map(|named_attribute| named_attribute.into_owned())
.collect(),
delimiter: delimiter.map(to_owned_cow),
name: to_owned_cow(name),
},
MailboxDatum::Search(seqs) => MailboxDatum::Search(seqs),
MailboxDatum::Sort(seqs) => MailboxDatum::Sort(seqs),
MailboxDatum::Status { mailbox, status } => MailboxDatum::Status {
mailbox: to_owned_cow(mailbox),
status,
},
MailboxDatum::Recent(seq) => MailboxDatum::Recent(seq),
MailboxDatum::MetadataSolicited { mailbox, values } => {
MailboxDatum::MetadataSolicited {
mailbox: to_owned_cow(mailbox),
values,
}
}
MailboxDatum::MetadataUnsolicited { mailbox, values } => {
MailboxDatum::MetadataUnsolicited {
mailbox: to_owned_cow(mailbox),
values: values.into_iter().map(to_owned_cow).collect(),
}
}
MailboxDatum::GmailLabels(labels) => {
MailboxDatum::GmailLabels(labels.into_iter().map(to_owned_cow).collect())
}
MailboxDatum::GmailMsgId(msgid) => MailboxDatum::GmailMsgId(msgid),
}
}
}
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
Imap4rev1,
Auth(Cow<'a, str>),
Atom(Cow<'a, str>),
}
impl<'a> Capability<'a> {
pub fn into_owned(self) -> Capability<'static> {
match self {
Capability::Imap4rev1 => Capability::Imap4rev1,
Capability::Auth(v) => Capability::Auth(to_owned_cow(v)),
Capability::Atom(v) => Capability::Atom(to_owned_cow(v)),
}
}
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Attribute {
Body,
Envelope,
Flags,
InternalDate,
ModSeq, Rfc822,
Rfc822Size,
Rfc822Text,
Uid,
GmailLabels,
GmailMsgId,
}
#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
Header,
Mime,
Text,
}
#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
Full(MessageSection),
Part(Vec<u32>, Option<MessageSection>),
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum AttributeValue<'a> {
BodySection {
section: Option<SectionPath>,
index: Option<u32>,
data: Option<Cow<'a, [u8]>>,
},
BodyStructure(BodyStructure<'a>),
Envelope(Box<Envelope<'a>>),
Flags(Vec<Cow<'a, str>>),
InternalDate(Cow<'a, str>),
ModSeq(u64), Rfc822(Option<Cow<'a, [u8]>>),
Rfc822Header(Option<Cow<'a, [u8]>>),
Rfc822Size(u32),
Rfc822Text(Option<Cow<'a, [u8]>>),
Uid(u32),
GmailLabels(Vec<Cow<'a, str>>),
GmailMsgId(u64),
}
impl<'a> AttributeValue<'a> {
pub fn into_owned(self) -> AttributeValue<'static> {
match self {
AttributeValue::BodySection {
section,
index,
data,
} => AttributeValue::BodySection {
section,
index,
data: data.map(to_owned_cow),
},
AttributeValue::BodyStructure(body) => AttributeValue::BodyStructure(body.into_owned()),
AttributeValue::Envelope(e) => AttributeValue::Envelope(Box::new(e.into_owned())),
AttributeValue::Flags(v) => {
AttributeValue::Flags(v.into_iter().map(to_owned_cow).collect())
}
AttributeValue::InternalDate(v) => AttributeValue::InternalDate(to_owned_cow(v)),
AttributeValue::ModSeq(v) => AttributeValue::ModSeq(v),
AttributeValue::Rfc822(v) => AttributeValue::Rfc822(v.map(to_owned_cow)),
AttributeValue::Rfc822Header(v) => AttributeValue::Rfc822Header(v.map(to_owned_cow)),
AttributeValue::Rfc822Size(v) => AttributeValue::Rfc822Size(v),
AttributeValue::Rfc822Text(v) => AttributeValue::Rfc822Text(v.map(to_owned_cow)),
AttributeValue::Uid(v) => AttributeValue::Uid(v),
AttributeValue::GmailLabels(v) => {
AttributeValue::GmailLabels(v.into_iter().map(to_owned_cow).collect())
}
AttributeValue::GmailMsgId(v) => AttributeValue::GmailMsgId(v),
}
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
Basic {
common: BodyContentCommon<'a>,
other: BodyContentSinglePart<'a>,
extension: Option<BodyExtension<'a>>,
},
Text {
common: BodyContentCommon<'a>,
other: BodyContentSinglePart<'a>,
lines: u32,
extension: Option<BodyExtension<'a>>,
},
Message {
common: BodyContentCommon<'a>,
other: BodyContentSinglePart<'a>,
envelope: Envelope<'a>,
body: Box<BodyStructure<'a>>,
lines: u32,
extension: Option<BodyExtension<'a>>,
},
Multipart {
common: BodyContentCommon<'a>,
bodies: Vec<BodyStructure<'a>>,
extension: Option<BodyExtension<'a>>,
},
}
impl<'a> BodyStructure<'a> {
pub fn into_owned(self) -> BodyStructure<'static> {
match self {
BodyStructure::Basic {
common,
other,
extension,
} => BodyStructure::Basic {
common: common.into_owned(),
other: other.into_owned(),
extension: extension.map(|v| v.into_owned()),
},
BodyStructure::Text {
common,
other,
lines,
extension,
} => BodyStructure::Text {
common: common.into_owned(),
other: other.into_owned(),
lines,
extension: extension.map(|v| v.into_owned()),
},
BodyStructure::Message {
common,
other,
envelope,
body,
lines,
extension,
} => BodyStructure::Message {
common: common.into_owned(),
other: other.into_owned(),
envelope: envelope.into_owned(),
body: Box::new(body.into_owned()),
lines,
extension: extension.map(|v| v.into_owned()),
},
BodyStructure::Multipart {
common,
bodies,
extension,
} => BodyStructure::Multipart {
common: common.into_owned(),
bodies: bodies.into_iter().map(|v| v.into_owned()).collect(),
extension: extension.map(|v| v.into_owned()),
},
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
pub ty: ContentType<'a>,
pub disposition: Option<ContentDisposition<'a>>,
pub language: Option<Vec<Cow<'a, str>>>,
pub location: Option<Cow<'a, str>>,
}
impl<'a> BodyContentCommon<'a> {
pub fn into_owned(self) -> BodyContentCommon<'static> {
BodyContentCommon {
ty: self.ty.into_owned(),
disposition: self.disposition.map(|v| v.into_owned()),
language: self
.language
.map(|v| v.into_iter().map(to_owned_cow).collect()),
location: self.location.map(to_owned_cow),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
pub id: Option<Cow<'a, str>>,
pub md5: Option<Cow<'a, str>>,
pub description: Option<Cow<'a, str>>,
pub transfer_encoding: ContentEncoding<'a>,
pub octets: u32,
}
impl<'a> BodyContentSinglePart<'a> {
pub fn into_owned(self) -> BodyContentSinglePart<'static> {
BodyContentSinglePart {
id: self.id.map(to_owned_cow),
md5: self.md5.map(to_owned_cow),
description: self.description.map(to_owned_cow),
transfer_encoding: self.transfer_encoding.into_owned(),
octets: self.octets,
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
pub ty: Cow<'a, str>,
pub subtype: Cow<'a, str>,
pub params: BodyParams<'a>,
}
impl<'a> ContentType<'a> {
pub fn into_owned(self) -> ContentType<'static> {
ContentType {
ty: to_owned_cow(self.ty),
subtype: to_owned_cow(self.subtype),
params: body_param_owned(self.params),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
pub ty: Cow<'a, str>,
pub params: BodyParams<'a>,
}
impl<'a> ContentDisposition<'a> {
pub fn into_owned(self) -> ContentDisposition<'static> {
ContentDisposition {
ty: to_owned_cow(self.ty),
params: body_param_owned(self.params),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
SevenBit,
EightBit,
Binary,
Base64,
QuotedPrintable,
Other(Cow<'a, str>),
}
impl<'a> ContentEncoding<'a> {
pub fn into_owned(self) -> ContentEncoding<'static> {
match self {
ContentEncoding::SevenBit => ContentEncoding::SevenBit,
ContentEncoding::EightBit => ContentEncoding::EightBit,
ContentEncoding::Binary => ContentEncoding::Binary,
ContentEncoding::Base64 => ContentEncoding::Base64,
ContentEncoding::QuotedPrintable => ContentEncoding::QuotedPrintable,
ContentEncoding::Other(v) => ContentEncoding::Other(to_owned_cow(v)),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
Num(u32),
Str(Option<Cow<'a, str>>),
List(Vec<BodyExtension<'a>>),
}
impl<'a> BodyExtension<'a> {
pub fn into_owned(self) -> BodyExtension<'static> {
match self {
BodyExtension::Num(v) => BodyExtension::Num(v),
BodyExtension::Str(v) => BodyExtension::Str(v.map(to_owned_cow)),
BodyExtension::List(v) => {
BodyExtension::List(v.into_iter().map(|v| v.into_owned()).collect())
}
}
}
}
pub type BodyParams<'a> = Option<Vec<(Cow<'a, str>, Cow<'a, str>)>>;
fn body_param_owned(v: BodyParams<'_>) -> BodyParams<'static> {
v.map(|v| {
v.into_iter()
.map(|(k, v)| (to_owned_cow(k), to_owned_cow(v)))
.collect()
})
}
#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
pub date: Option<Cow<'a, [u8]>>,
pub subject: Option<Cow<'a, [u8]>>,
pub from: Option<Vec<Address<'a>>>,
pub sender: Option<Vec<Address<'a>>>,
pub reply_to: Option<Vec<Address<'a>>>,
pub to: Option<Vec<Address<'a>>>,
pub cc: Option<Vec<Address<'a>>>,
pub bcc: Option<Vec<Address<'a>>>,
pub in_reply_to: Option<Cow<'a, [u8]>>,
pub message_id: Option<Cow<'a, [u8]>>,
}
impl<'a> Envelope<'a> {
pub fn into_owned(self) -> Envelope<'static> {
Envelope {
date: self.date.map(to_owned_cow),
subject: self.subject.map(to_owned_cow),
from: self
.from
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
sender: self
.sender
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
reply_to: self
.reply_to
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
to: self
.to
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
cc: self
.cc
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
bcc: self
.bcc
.map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
in_reply_to: self.in_reply_to.map(to_owned_cow),
message_id: self.message_id.map(to_owned_cow),
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
pub name: Option<Cow<'a, [u8]>>,
pub adl: Option<Cow<'a, [u8]>>,
pub mailbox: Option<Cow<'a, [u8]>>,
pub host: Option<Cow<'a, [u8]>>,
}
impl<'a> Address<'a> {
pub fn into_owned(self) -> Address<'static> {
Address {
name: self.name.map(to_owned_cow),
adl: self.adl.map(to_owned_cow),
mailbox: self.mailbox.map(to_owned_cow),
host: self.host.map(to_owned_cow),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);
impl RequestId {
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum State {
NotAuthenticated,
Authenticated,
Selected,
Logout,
}
pub struct BodyFields<'a> {
pub param: BodyParams<'a>,
pub id: Option<Cow<'a, str>>,
pub description: Option<Cow<'a, str>>,
pub transfer_encoding: ContentEncoding<'a>,
pub octets: u32,
}
impl<'a> BodyFields<'a> {
pub fn into_owned(self) -> BodyFields<'static> {
BodyFields {
param: body_param_owned(self.param),
id: self.id.map(to_owned_cow),
description: self.description.map(to_owned_cow),
transfer_encoding: self.transfer_encoding.into_owned(),
octets: self.octets,
}
}
}
pub struct BodyExt1Part<'a> {
pub md5: Option<Cow<'a, str>>,
pub disposition: Option<ContentDisposition<'a>>,
pub language: Option<Vec<Cow<'a, str>>>,
pub location: Option<Cow<'a, str>>,
pub extension: Option<BodyExtension<'a>>,
}
impl<'a> BodyExt1Part<'a> {
pub fn into_owned(self) -> BodyExt1Part<'static> {
BodyExt1Part {
md5: self.md5.map(to_owned_cow),
disposition: self.disposition.map(|v| v.into_owned()),
language: self
.language
.map(|v| v.into_iter().map(to_owned_cow).collect()),
location: self.location.map(to_owned_cow),
extension: self.extension.map(|v| v.into_owned()),
}
}
}
pub struct BodyExtMPart<'a> {
pub param: BodyParams<'a>,
pub disposition: Option<ContentDisposition<'a>>,
pub language: Option<Vec<Cow<'a, str>>>,
pub location: Option<Cow<'a, str>>,
pub extension: Option<BodyExtension<'a>>,
}
impl<'a> BodyExtMPart<'a> {
pub fn into_owned(self) -> BodyExtMPart<'static> {
BodyExtMPart {
param: body_param_owned(self.param),
disposition: self.disposition.map(|v| v.into_owned()),
language: self
.language
.map(|v| v.into_iter().map(to_owned_cow).collect()),
location: self.location.map(to_owned_cow),
extension: self.extension.map(|v| v.into_owned()),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
#[non_exhaustive]
pub enum NameAttribute<'a> {
NoInferiors,
NoSelect,
Marked,
Unmarked,
All,
Archive,
Drafts,
Flagged,
Junk,
Sent,
Trash,
Extension(Cow<'a, str>),
}
impl<'a> NameAttribute<'a> {
pub fn into_owned(self) -> NameAttribute<'static> {
match self {
NameAttribute::NoInferiors => NameAttribute::NoInferiors,
NameAttribute::NoSelect => NameAttribute::NoSelect,
NameAttribute::Marked => NameAttribute::Marked,
NameAttribute::Unmarked => NameAttribute::Unmarked,
NameAttribute::All => NameAttribute::All,
NameAttribute::Archive => NameAttribute::Archive,
NameAttribute::Drafts => NameAttribute::Drafts,
NameAttribute::Flagged => NameAttribute::Flagged,
NameAttribute::Junk => NameAttribute::Junk,
NameAttribute::Sent => NameAttribute::Sent,
NameAttribute::Trash => NameAttribute::Trash,
NameAttribute::Extension(s) => NameAttribute::Extension(to_owned_cow(s)),
}
}
}
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub enum QuotaResourceName<'a> {
Storage,
Message,
Atom(Cow<'a, str>),
}
impl<'a> QuotaResourceName<'a> {
pub fn into_owned(self) -> QuotaResourceName<'static> {
match self {
QuotaResourceName::Message => QuotaResourceName::Message,
QuotaResourceName::Storage => QuotaResourceName::Storage,
QuotaResourceName::Atom(v) => QuotaResourceName::Atom(to_owned_cow(v)),
}
}
}
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct QuotaResource<'a> {
pub name: QuotaResourceName<'a>,
pub usage: u64,
pub limit: u64,
}
impl<'a> QuotaResource<'a> {
pub fn into_owned(self) -> QuotaResource<'static> {
QuotaResource {
name: self.name.into_owned(),
usage: self.usage,
limit: self.limit,
}
}
}
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct Quota<'a> {
pub root_name: Cow<'a, str>,
pub resources: Vec<QuotaResource<'a>>,
}
impl<'a> Quota<'a> {
pub fn into_owned(self) -> Quota<'static> {
Quota {
root_name: to_owned_cow(self.root_name),
resources: self.resources.into_iter().map(|r| r.into_owned()).collect(),
}
}
}
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct QuotaRoot<'a> {
pub mailbox_name: Cow<'a, str>,
pub quota_root_names: Vec<Cow<'a, str>>,
}
impl<'a> QuotaRoot<'a> {
pub fn into_owned(self) -> QuotaRoot<'static> {
QuotaRoot {
mailbox_name: to_owned_cow(self.mailbox_name),
quota_root_names: self
.quota_root_names
.into_iter()
.map(to_owned_cow)
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_name_attribute_into_owned() {
let name_attributes = [
NameAttribute::NoInferiors,
NameAttribute::NoSelect,
NameAttribute::Marked,
NameAttribute::Unmarked,
NameAttribute::All,
NameAttribute::Archive,
NameAttribute::Drafts,
NameAttribute::Flagged,
NameAttribute::Junk,
NameAttribute::Sent,
NameAttribute::Trash,
NameAttribute::Extension(Cow::Borrowed("Foobar")),
];
for name_attribute in name_attributes {
let owned_name_attribute = name_attribute.clone().into_owned();
assert_eq!(name_attribute, owned_name_attribute);
}
}
}