1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::ops::RangeInclusive;
4
5pub mod acls;
6pub use acls::*;
7
8fn to_owned_cow<T: ?Sized + ToOwned>(c: Cow<'_, T>) -> Cow<'static, T> {
9 Cow::Owned(c.into_owned())
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct Request<'a>(pub Cow<'a, [u8]>, pub Cow<'a, [u8]>);
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub enum AttrMacro {
17 All,
18 Fast,
19 Full,
20}
21
22#[derive(Debug, Eq, PartialEq)]
23#[non_exhaustive]
24pub enum Response<'a> {
25 Capabilities(Vec<Capability<'a>>),
26 Continue {
27 code: Option<ResponseCode<'a>>,
28 information: Option<Cow<'a, str>>,
29 },
30 Done {
31 tag: RequestId,
32 status: Status,
33 code: Option<ResponseCode<'a>>,
34 information: Option<Cow<'a, str>>,
35 },
36 Data {
37 status: Status,
38 code: Option<ResponseCode<'a>>,
39 information: Option<Cow<'a, str>>,
40 },
41 Expunge(u32),
42 Vanished {
43 earlier: bool,
44 uids: Vec<std::ops::RangeInclusive<u32>>,
45 },
46 Fetch(u32, Vec<AttributeValue<'a>>),
47 MailboxData(MailboxDatum<'a>),
48 Quota(Quota<'a>),
49 QuotaRoot(QuotaRoot<'a>),
50 Id(Option<HashMap<Cow<'a, str>, Cow<'a, str>>>),
51 Acl(Acl<'a>),
52 ListRights(ListRights<'a>),
53 MyRights(MyRights<'a>),
54}
55
56impl<'a> Response<'a> {
57 pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult<'a> {
58 crate::parser::parse_response(buf)
59 }
60
61 pub fn into_owned(self) -> Response<'static> {
62 match self {
63 Response::Capabilities(capabilities) => Response::Capabilities(
64 capabilities
65 .into_iter()
66 .map(Capability::into_owned)
67 .collect(),
68 ),
69 Response::Continue { code, information } => Response::Continue {
70 code: code.map(ResponseCode::into_owned),
71 information: information.map(to_owned_cow),
72 },
73 Response::Done {
74 tag,
75 status,
76 code,
77 information,
78 } => Response::Done {
79 tag,
80 status,
81 code: code.map(ResponseCode::into_owned),
82 information: information.map(to_owned_cow),
83 },
84 Response::Data {
85 status,
86 code,
87 information,
88 } => Response::Data {
89 status,
90 code: code.map(ResponseCode::into_owned),
91 information: information.map(to_owned_cow),
92 },
93 Response::Expunge(seq) => Response::Expunge(seq),
94 Response::Vanished { earlier, uids } => Response::Vanished { earlier, uids },
95 Response::Fetch(seq, attrs) => Response::Fetch(
96 seq,
97 attrs.into_iter().map(AttributeValue::into_owned).collect(),
98 ),
99 Response::MailboxData(datum) => Response::MailboxData(datum.into_owned()),
100 Response::Quota(quota) => Response::Quota(quota.into_owned()),
101 Response::QuotaRoot(quota_root) => Response::QuotaRoot(quota_root.into_owned()),
102 Response::Id(map) => Response::Id(map.map(|m| {
103 m.into_iter()
104 .map(|(k, v)| (to_owned_cow(k), to_owned_cow(v)))
105 .collect()
106 })),
107 Response::Acl(acl_list) => Response::Acl(acl_list.into_owned()),
108 Response::ListRights(rights) => Response::ListRights(rights.into_owned()),
109 Response::MyRights(rights) => Response::MyRights(rights.into_owned()),
110 }
111 }
112}
113
114#[derive(Debug, Eq, PartialEq)]
115pub enum Status {
116 Ok,
117 No,
118 Bad,
119 PreAuth,
120 Bye,
121}
122
123#[derive(Debug, Eq, PartialEq)]
124#[non_exhaustive]
125pub enum ResponseCode<'a> {
126 Alert,
127 BadCharset(Option<Vec<Cow<'a, str>>>),
128 Capabilities(Vec<Capability<'a>>),
129 HighestModSeq(u64), Parse,
131 PermanentFlags(Vec<Cow<'a, str>>),
132 ReadOnly,
133 ReadWrite,
134 TryCreate,
135 UidNext(u32),
136 UidValidity(u32),
137 Unseen(u32),
138 AppendUid(u32, Vec<UidSetMember>),
139 CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
140 UidNotSticky,
141 MetadataLongEntries(u64), MetadataMaxSize(u64), MetadataTooMany, MetadataNoPrivate, }
146
147#[derive(Clone, Debug, Eq, PartialEq)]
148pub enum UidSetMember {
149 UidRange(RangeInclusive<u32>),
150 Uid(u32),
151}
152
153impl From<RangeInclusive<u32>> for UidSetMember {
154 fn from(x: RangeInclusive<u32>) -> Self {
155 UidSetMember::UidRange(x)
156 }
157}
158
159impl From<u32> for UidSetMember {
160 fn from(x: u32) -> Self {
161 UidSetMember::Uid(x)
162 }
163}
164
165impl<'a> ResponseCode<'a> {
166 pub fn into_owned(self) -> ResponseCode<'static> {
167 match self {
168 ResponseCode::Alert => ResponseCode::Alert,
169 ResponseCode::BadCharset(v) => {
170 ResponseCode::BadCharset(v.map(|vs| vs.into_iter().map(to_owned_cow).collect()))
171 }
172 ResponseCode::Capabilities(v) => {
173 ResponseCode::Capabilities(v.into_iter().map(Capability::into_owned).collect())
174 }
175 ResponseCode::HighestModSeq(v) => ResponseCode::HighestModSeq(v),
176 ResponseCode::Parse => ResponseCode::Parse,
177 ResponseCode::PermanentFlags(v) => {
178 ResponseCode::PermanentFlags(v.into_iter().map(to_owned_cow).collect())
179 }
180 ResponseCode::ReadOnly => ResponseCode::ReadOnly,
181 ResponseCode::ReadWrite => ResponseCode::ReadWrite,
182 ResponseCode::TryCreate => ResponseCode::TryCreate,
183 ResponseCode::UidNext(v) => ResponseCode::UidNext(v),
184 ResponseCode::UidValidity(v) => ResponseCode::UidValidity(v),
185 ResponseCode::Unseen(v) => ResponseCode::Unseen(v),
186 ResponseCode::AppendUid(a, b) => ResponseCode::AppendUid(a, b),
187 ResponseCode::CopyUid(a, b, c) => ResponseCode::CopyUid(a, b, c),
188 ResponseCode::UidNotSticky => ResponseCode::UidNotSticky,
189 ResponseCode::MetadataLongEntries(v) => ResponseCode::MetadataLongEntries(v),
190 ResponseCode::MetadataMaxSize(v) => ResponseCode::MetadataMaxSize(v),
191 ResponseCode::MetadataTooMany => ResponseCode::MetadataTooMany,
192 ResponseCode::MetadataNoPrivate => ResponseCode::MetadataNoPrivate,
193 }
194 }
195}
196
197#[derive(Debug, Eq, PartialEq, Clone)]
198#[non_exhaustive]
199pub enum StatusAttribute {
200 HighestModSeq(u64), Messages(u32),
202 Recent(u32),
203 UidNext(u32),
204 UidValidity(u32),
205 Unseen(u32),
206}
207
208#[derive(Debug, Eq, PartialEq, Clone)]
209pub struct Metadata {
210 pub entry: String,
211 pub value: Option<String>,
212}
213
214#[derive(Debug, Eq, PartialEq, Clone)]
215#[non_exhaustive]
216pub enum MailboxDatum<'a> {
217 Exists(u32),
218 Flags(Vec<Cow<'a, str>>),
219 List {
220 name_attributes: Vec<NameAttribute<'a>>,
221 delimiter: Option<Cow<'a, str>>,
222 name: Cow<'a, str>,
223 },
224 Search(Vec<u32>),
225 Sort(Vec<u32>),
226 Status {
227 mailbox: Cow<'a, str>,
228 status: Vec<StatusAttribute>,
229 },
230 Recent(u32),
231 MetadataSolicited {
232 mailbox: Cow<'a, str>,
233 values: Vec<Metadata>,
234 },
235 MetadataUnsolicited {
236 mailbox: Cow<'a, str>,
237 values: Vec<Cow<'a, str>>,
238 },
239 GmailLabels(Vec<Cow<'a, str>>),
240 GmailMsgId(u64),
241}
242
243impl<'a> MailboxDatum<'a> {
244 pub fn into_owned(self) -> MailboxDatum<'static> {
245 match self {
246 MailboxDatum::Exists(seq) => MailboxDatum::Exists(seq),
247 MailboxDatum::Flags(flags) => {
248 MailboxDatum::Flags(flags.into_iter().map(to_owned_cow).collect())
249 }
250 MailboxDatum::List {
251 name_attributes,
252 delimiter,
253 name,
254 } => MailboxDatum::List {
255 name_attributes: name_attributes
256 .into_iter()
257 .map(|named_attribute| named_attribute.into_owned())
258 .collect(),
259 delimiter: delimiter.map(to_owned_cow),
260 name: to_owned_cow(name),
261 },
262 MailboxDatum::Search(seqs) => MailboxDatum::Search(seqs),
263 MailboxDatum::Sort(seqs) => MailboxDatum::Sort(seqs),
264 MailboxDatum::Status { mailbox, status } => MailboxDatum::Status {
265 mailbox: to_owned_cow(mailbox),
266 status,
267 },
268 MailboxDatum::Recent(seq) => MailboxDatum::Recent(seq),
269 MailboxDatum::MetadataSolicited { mailbox, values } => {
270 MailboxDatum::MetadataSolicited {
271 mailbox: to_owned_cow(mailbox),
272 values,
273 }
274 }
275 MailboxDatum::MetadataUnsolicited { mailbox, values } => {
276 MailboxDatum::MetadataUnsolicited {
277 mailbox: to_owned_cow(mailbox),
278 values: values.into_iter().map(to_owned_cow).collect(),
279 }
280 }
281 MailboxDatum::GmailLabels(labels) => {
282 MailboxDatum::GmailLabels(labels.into_iter().map(to_owned_cow).collect())
283 }
284 MailboxDatum::GmailMsgId(msgid) => MailboxDatum::GmailMsgId(msgid),
285 }
286 }
287}
288
289#[derive(Debug, Eq, PartialEq, Hash)]
290pub enum Capability<'a> {
291 Imap4rev1,
292 Auth(Cow<'a, str>),
293 Atom(Cow<'a, str>),
294}
295
296impl<'a> Capability<'a> {
297 pub fn into_owned(self) -> Capability<'static> {
298 match self {
299 Capability::Imap4rev1 => Capability::Imap4rev1,
300 Capability::Auth(v) => Capability::Auth(to_owned_cow(v)),
301 Capability::Atom(v) => Capability::Atom(to_owned_cow(v)),
302 }
303 }
304}
305
306#[derive(Debug, Eq, PartialEq)]
307#[non_exhaustive]
308pub enum Attribute {
309 Body,
310 Envelope,
311 Flags,
312 InternalDate,
313 ModSeq, Rfc822,
315 Rfc822Size,
316 Rfc822Text,
317 Uid,
318 GmailLabels,
320 GmailMsgId,
321}
322
323#[derive(Debug, Eq, PartialEq)]
324pub enum MessageSection {
325 Header,
326 Mime,
327 Text,
328}
329
330#[derive(Debug, Eq, PartialEq)]
331pub enum SectionPath {
332 Full(MessageSection),
333 Part(Vec<u32>, Option<MessageSection>),
334}
335
336#[allow(clippy::large_enum_variant)]
337#[derive(Debug, Eq, PartialEq)]
338#[non_exhaustive]
339pub enum AttributeValue<'a> {
340 BodySection {
341 section: Option<SectionPath>,
342 index: Option<u32>,
343 data: Option<Cow<'a, [u8]>>,
344 },
345 BodyStructure(BodyStructure<'a>),
346 Envelope(Box<Envelope<'a>>),
347 Flags(Vec<Cow<'a, str>>),
348 InternalDate(Cow<'a, str>),
349 ModSeq(u64), Rfc822(Option<Cow<'a, [u8]>>),
351 Rfc822Header(Option<Cow<'a, [u8]>>),
352 Rfc822Size(u32),
353 Rfc822Text(Option<Cow<'a, [u8]>>),
354 Uid(u32),
355 GmailLabels(Vec<Cow<'a, str>>),
357 GmailMsgId(u64),
358}
359
360impl<'a> AttributeValue<'a> {
361 pub fn into_owned(self) -> AttributeValue<'static> {
362 match self {
363 AttributeValue::BodySection {
364 section,
365 index,
366 data,
367 } => AttributeValue::BodySection {
368 section,
369 index,
370 data: data.map(to_owned_cow),
371 },
372 AttributeValue::BodyStructure(body) => AttributeValue::BodyStructure(body.into_owned()),
373 AttributeValue::Envelope(e) => AttributeValue::Envelope(Box::new(e.into_owned())),
374 AttributeValue::Flags(v) => {
375 AttributeValue::Flags(v.into_iter().map(to_owned_cow).collect())
376 }
377 AttributeValue::InternalDate(v) => AttributeValue::InternalDate(to_owned_cow(v)),
378 AttributeValue::ModSeq(v) => AttributeValue::ModSeq(v),
379 AttributeValue::Rfc822(v) => AttributeValue::Rfc822(v.map(to_owned_cow)),
380 AttributeValue::Rfc822Header(v) => AttributeValue::Rfc822Header(v.map(to_owned_cow)),
381 AttributeValue::Rfc822Size(v) => AttributeValue::Rfc822Size(v),
382 AttributeValue::Rfc822Text(v) => AttributeValue::Rfc822Text(v.map(to_owned_cow)),
383 AttributeValue::Uid(v) => AttributeValue::Uid(v),
384 AttributeValue::GmailLabels(v) => {
385 AttributeValue::GmailLabels(v.into_iter().map(to_owned_cow).collect())
386 }
387 AttributeValue::GmailMsgId(v) => AttributeValue::GmailMsgId(v),
388 }
389 }
390}
391
392#[allow(clippy::large_enum_variant)]
393#[derive(Debug, Eq, PartialEq)]
394pub enum BodyStructure<'a> {
395 Basic {
396 common: BodyContentCommon<'a>,
397 other: BodyContentSinglePart<'a>,
398 extension: Option<BodyExtension<'a>>,
399 },
400 Text {
401 common: BodyContentCommon<'a>,
402 other: BodyContentSinglePart<'a>,
403 lines: u32,
404 extension: Option<BodyExtension<'a>>,
405 },
406 Message {
407 common: BodyContentCommon<'a>,
408 other: BodyContentSinglePart<'a>,
409 envelope: Envelope<'a>,
410 body: Box<BodyStructure<'a>>,
411 lines: u32,
412 extension: Option<BodyExtension<'a>>,
413 },
414 Multipart {
415 common: BodyContentCommon<'a>,
416 bodies: Vec<BodyStructure<'a>>,
417 extension: Option<BodyExtension<'a>>,
418 },
419}
420
421impl<'a> BodyStructure<'a> {
422 pub fn into_owned(self) -> BodyStructure<'static> {
423 match self {
424 BodyStructure::Basic {
425 common,
426 other,
427 extension,
428 } => BodyStructure::Basic {
429 common: common.into_owned(),
430 other: other.into_owned(),
431 extension: extension.map(|v| v.into_owned()),
432 },
433 BodyStructure::Text {
434 common,
435 other,
436 lines,
437 extension,
438 } => BodyStructure::Text {
439 common: common.into_owned(),
440 other: other.into_owned(),
441 lines,
442 extension: extension.map(|v| v.into_owned()),
443 },
444 BodyStructure::Message {
445 common,
446 other,
447 envelope,
448 body,
449 lines,
450 extension,
451 } => BodyStructure::Message {
452 common: common.into_owned(),
453 other: other.into_owned(),
454 envelope: envelope.into_owned(),
455 body: Box::new(body.into_owned()),
456 lines,
457 extension: extension.map(|v| v.into_owned()),
458 },
459 BodyStructure::Multipart {
460 common,
461 bodies,
462 extension,
463 } => BodyStructure::Multipart {
464 common: common.into_owned(),
465 bodies: bodies.into_iter().map(|v| v.into_owned()).collect(),
466 extension: extension.map(|v| v.into_owned()),
467 },
468 }
469 }
470}
471
472#[derive(Debug, Eq, PartialEq)]
473pub struct BodyContentCommon<'a> {
474 pub ty: ContentType<'a>,
475 pub disposition: Option<ContentDisposition<'a>>,
476 pub language: Option<Vec<Cow<'a, str>>>,
477 pub location: Option<Cow<'a, str>>,
478}
479
480impl<'a> BodyContentCommon<'a> {
481 pub fn into_owned(self) -> BodyContentCommon<'static> {
482 BodyContentCommon {
483 ty: self.ty.into_owned(),
484 disposition: self.disposition.map(|v| v.into_owned()),
485 language: self
486 .language
487 .map(|v| v.into_iter().map(to_owned_cow).collect()),
488 location: self.location.map(to_owned_cow),
489 }
490 }
491}
492
493#[derive(Debug, Eq, PartialEq)]
494pub struct BodyContentSinglePart<'a> {
495 pub id: Option<Cow<'a, str>>,
496 pub md5: Option<Cow<'a, str>>,
497 pub description: Option<Cow<'a, str>>,
498 pub transfer_encoding: ContentEncoding<'a>,
499 pub octets: u32,
500}
501
502impl<'a> BodyContentSinglePart<'a> {
503 pub fn into_owned(self) -> BodyContentSinglePart<'static> {
504 BodyContentSinglePart {
505 id: self.id.map(to_owned_cow),
506 md5: self.md5.map(to_owned_cow),
507 description: self.description.map(to_owned_cow),
508 transfer_encoding: self.transfer_encoding.into_owned(),
509 octets: self.octets,
510 }
511 }
512}
513
514#[derive(Debug, Eq, PartialEq)]
515pub struct ContentType<'a> {
516 pub ty: Cow<'a, str>,
517 pub subtype: Cow<'a, str>,
518 pub params: BodyParams<'a>,
519}
520
521impl<'a> ContentType<'a> {
522 pub fn into_owned(self) -> ContentType<'static> {
523 ContentType {
524 ty: to_owned_cow(self.ty),
525 subtype: to_owned_cow(self.subtype),
526 params: body_param_owned(self.params),
527 }
528 }
529}
530
531#[derive(Debug, Eq, PartialEq)]
532pub struct ContentDisposition<'a> {
533 pub ty: Cow<'a, str>,
534 pub params: BodyParams<'a>,
535}
536
537impl<'a> ContentDisposition<'a> {
538 pub fn into_owned(self) -> ContentDisposition<'static> {
539 ContentDisposition {
540 ty: to_owned_cow(self.ty),
541 params: body_param_owned(self.params),
542 }
543 }
544}
545
546#[derive(Debug, Eq, PartialEq)]
547pub enum ContentEncoding<'a> {
548 SevenBit,
549 EightBit,
550 Binary,
551 Base64,
552 QuotedPrintable,
553 Other(Cow<'a, str>),
554}
555
556impl<'a> ContentEncoding<'a> {
557 pub fn into_owned(self) -> ContentEncoding<'static> {
558 match self {
559 ContentEncoding::SevenBit => ContentEncoding::SevenBit,
560 ContentEncoding::EightBit => ContentEncoding::EightBit,
561 ContentEncoding::Binary => ContentEncoding::Binary,
562 ContentEncoding::Base64 => ContentEncoding::Base64,
563 ContentEncoding::QuotedPrintable => ContentEncoding::QuotedPrintable,
564 ContentEncoding::Other(v) => ContentEncoding::Other(to_owned_cow(v)),
565 }
566 }
567}
568
569#[derive(Debug, Eq, PartialEq)]
570pub enum BodyExtension<'a> {
571 Num(u32),
572 Str(Option<Cow<'a, str>>),
573 List(Vec<BodyExtension<'a>>),
574}
575
576impl<'a> BodyExtension<'a> {
577 pub fn into_owned(self) -> BodyExtension<'static> {
578 match self {
579 BodyExtension::Num(v) => BodyExtension::Num(v),
580 BodyExtension::Str(v) => BodyExtension::Str(v.map(to_owned_cow)),
581 BodyExtension::List(v) => {
582 BodyExtension::List(v.into_iter().map(|v| v.into_owned()).collect())
583 }
584 }
585 }
586}
587
588pub type BodyParams<'a> = Option<Vec<(Cow<'a, str>, Cow<'a, str>)>>;
589
590fn body_param_owned(v: BodyParams<'_>) -> BodyParams<'static> {
591 v.map(|v| {
592 v.into_iter()
593 .map(|(k, v)| (to_owned_cow(k), to_owned_cow(v)))
594 .collect()
595 })
596}
597
598#[derive(Debug, Eq, PartialEq)]
602pub struct Envelope<'a> {
603 pub date: Option<Cow<'a, [u8]>>,
604 pub subject: Option<Cow<'a, [u8]>>,
605 pub from: Option<Vec<Address<'a>>>,
607 pub sender: Option<Vec<Address<'a>>>,
609 pub reply_to: Option<Vec<Address<'a>>>,
611 pub to: Option<Vec<Address<'a>>>,
612 pub cc: Option<Vec<Address<'a>>>,
613 pub bcc: Option<Vec<Address<'a>>>,
614 pub in_reply_to: Option<Cow<'a, [u8]>>,
615 pub message_id: Option<Cow<'a, [u8]>>,
616}
617
618impl<'a> Envelope<'a> {
619 pub fn into_owned(self) -> Envelope<'static> {
620 Envelope {
621 date: self.date.map(to_owned_cow),
622 subject: self.subject.map(to_owned_cow),
623 from: self
624 .from
625 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
626 sender: self
627 .sender
628 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
629 reply_to: self
630 .reply_to
631 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
632 to: self
633 .to
634 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
635 cc: self
636 .cc
637 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
638 bcc: self
639 .bcc
640 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
641 in_reply_to: self.in_reply_to.map(to_owned_cow),
642 message_id: self.message_id.map(to_owned_cow),
643 }
644 }
645}
646
647#[derive(Debug, Eq, PartialEq)]
648pub struct Address<'a> {
649 pub name: Option<Cow<'a, [u8]>>,
650 pub adl: Option<Cow<'a, [u8]>>,
651 pub mailbox: Option<Cow<'a, [u8]>>,
652 pub host: Option<Cow<'a, [u8]>>,
653}
654
655impl<'a> Address<'a> {
656 pub fn into_owned(self) -> Address<'static> {
657 Address {
658 name: self.name.map(to_owned_cow),
659 adl: self.adl.map(to_owned_cow),
660 mailbox: self.mailbox.map(to_owned_cow),
661 host: self.host.map(to_owned_cow),
662 }
663 }
664}
665
666#[derive(Clone, Debug, Eq, PartialEq)]
667pub struct RequestId(pub String);
668
669impl RequestId {
670 pub fn as_bytes(&self) -> &[u8] {
671 self.0.as_bytes()
672 }
673}
674
675#[derive(Clone, Copy, Debug, Eq, PartialEq)]
676pub enum State {
677 NotAuthenticated,
678 Authenticated,
679 Selected,
680 Logout,
681}
682
683pub struct BodyFields<'a> {
686 pub param: BodyParams<'a>,
687 pub id: Option<Cow<'a, str>>,
688 pub description: Option<Cow<'a, str>>,
689 pub transfer_encoding: ContentEncoding<'a>,
690 pub octets: u32,
691}
692
693impl<'a> BodyFields<'a> {
694 pub fn into_owned(self) -> BodyFields<'static> {
695 BodyFields {
696 param: body_param_owned(self.param),
697 id: self.id.map(to_owned_cow),
698 description: self.description.map(to_owned_cow),
699 transfer_encoding: self.transfer_encoding.into_owned(),
700 octets: self.octets,
701 }
702 }
703}
704
705pub struct BodyExt1Part<'a> {
706 pub md5: Option<Cow<'a, str>>,
707 pub disposition: Option<ContentDisposition<'a>>,
708 pub language: Option<Vec<Cow<'a, str>>>,
709 pub location: Option<Cow<'a, str>>,
710 pub extension: Option<BodyExtension<'a>>,
711}
712
713impl<'a> BodyExt1Part<'a> {
714 pub fn into_owned(self) -> BodyExt1Part<'static> {
715 BodyExt1Part {
716 md5: self.md5.map(to_owned_cow),
717 disposition: self.disposition.map(|v| v.into_owned()),
718 language: self
719 .language
720 .map(|v| v.into_iter().map(to_owned_cow).collect()),
721 location: self.location.map(to_owned_cow),
722 extension: self.extension.map(|v| v.into_owned()),
723 }
724 }
725}
726
727pub struct BodyExtMPart<'a> {
728 pub param: BodyParams<'a>,
729 pub disposition: Option<ContentDisposition<'a>>,
730 pub language: Option<Vec<Cow<'a, str>>>,
731 pub location: Option<Cow<'a, str>>,
732 pub extension: Option<BodyExtension<'a>>,
733}
734
735impl<'a> BodyExtMPart<'a> {
736 pub fn into_owned(self) -> BodyExtMPart<'static> {
737 BodyExtMPart {
738 param: body_param_owned(self.param),
739 disposition: self.disposition.map(|v| v.into_owned()),
740 language: self
741 .language
742 .map(|v| v.into_iter().map(to_owned_cow).collect()),
743 location: self.location.map(to_owned_cow),
744 extension: self.extension.map(|v| v.into_owned()),
745 }
746 }
747}
748
749#[derive(Debug, Eq, PartialEq, Clone)]
755#[non_exhaustive]
756pub enum NameAttribute<'a> {
757 NoInferiors,
763 NoSelect,
767 Marked,
773 Unmarked,
778 All,
785 Archive,
792 Drafts,
801 Flagged,
808 Junk,
815 Sent,
822 Trash,
834 Extension(Cow<'a, str>),
837}
838
839impl<'a> NameAttribute<'a> {
840 pub fn into_owned(self) -> NameAttribute<'static> {
841 match self {
842 NameAttribute::NoInferiors => NameAttribute::NoInferiors,
844 NameAttribute::NoSelect => NameAttribute::NoSelect,
845 NameAttribute::Marked => NameAttribute::Marked,
846 NameAttribute::Unmarked => NameAttribute::Unmarked,
847 NameAttribute::All => NameAttribute::All,
849 NameAttribute::Archive => NameAttribute::Archive,
850 NameAttribute::Drafts => NameAttribute::Drafts,
851 NameAttribute::Flagged => NameAttribute::Flagged,
852 NameAttribute::Junk => NameAttribute::Junk,
853 NameAttribute::Sent => NameAttribute::Sent,
854 NameAttribute::Trash => NameAttribute::Trash,
855 NameAttribute::Extension(s) => NameAttribute::Extension(to_owned_cow(s)),
857 }
858 }
859}
860
861#[derive(Debug, Eq, PartialEq, Hash, Clone)]
865pub enum QuotaResourceName<'a> {
866 Storage,
868 Message,
870 Atom(Cow<'a, str>),
871}
872
873impl<'a> QuotaResourceName<'a> {
874 pub fn into_owned(self) -> QuotaResourceName<'static> {
875 match self {
876 QuotaResourceName::Message => QuotaResourceName::Message,
877 QuotaResourceName::Storage => QuotaResourceName::Storage,
878 QuotaResourceName::Atom(v) => QuotaResourceName::Atom(to_owned_cow(v)),
879 }
880 }
881}
882
883#[derive(Debug, Eq, PartialEq, Hash, Clone)]
885pub struct QuotaResource<'a> {
886 pub name: QuotaResourceName<'a>,
887 pub usage: u64,
889 pub limit: u64,
891}
892
893impl<'a> QuotaResource<'a> {
894 pub fn into_owned(self) -> QuotaResource<'static> {
895 QuotaResource {
896 name: self.name.into_owned(),
897 usage: self.usage,
898 limit: self.limit,
899 }
900 }
901}
902
903#[derive(Debug, Eq, PartialEq, Hash, Clone)]
905pub struct Quota<'a> {
906 pub root_name: Cow<'a, str>,
908 pub resources: Vec<QuotaResource<'a>>,
909}
910
911impl<'a> Quota<'a> {
912 pub fn into_owned(self) -> Quota<'static> {
913 Quota {
914 root_name: to_owned_cow(self.root_name),
915 resources: self.resources.into_iter().map(|r| r.into_owned()).collect(),
916 }
917 }
918}
919
920#[derive(Debug, Eq, PartialEq, Hash, Clone)]
922pub struct QuotaRoot<'a> {
923 pub mailbox_name: Cow<'a, str>,
925 pub quota_root_names: Vec<Cow<'a, str>>,
927}
928
929impl<'a> QuotaRoot<'a> {
930 pub fn into_owned(self) -> QuotaRoot<'static> {
931 QuotaRoot {
932 mailbox_name: to_owned_cow(self.mailbox_name),
933 quota_root_names: self
934 .quota_root_names
935 .into_iter()
936 .map(to_owned_cow)
937 .collect(),
938 }
939 }
940}
941
942#[cfg(test)]
943mod tests {
944 use super::*;
945
946 #[test]
949 fn test_name_attribute_into_owned() {
950 let name_attributes = [
951 NameAttribute::NoInferiors,
953 NameAttribute::NoSelect,
954 NameAttribute::Marked,
955 NameAttribute::Unmarked,
956 NameAttribute::All,
958 NameAttribute::Archive,
959 NameAttribute::Drafts,
960 NameAttribute::Flagged,
961 NameAttribute::Junk,
962 NameAttribute::Sent,
963 NameAttribute::Trash,
964 NameAttribute::Extension(Cow::Borrowed("Foobar")),
966 ];
967
968 for name_attribute in name_attributes {
969 let owned_name_attribute = name_attribute.clone().into_owned();
970 assert_eq!(name_attribute, owned_name_attribute);
971 }
972 }
973}