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 GmailThrId(u64),
242}
243
244impl<'a> MailboxDatum<'a> {
245 pub fn into_owned(self) -> MailboxDatum<'static> {
246 match self {
247 MailboxDatum::Exists(seq) => MailboxDatum::Exists(seq),
248 MailboxDatum::Flags(flags) => {
249 MailboxDatum::Flags(flags.into_iter().map(to_owned_cow).collect())
250 }
251 MailboxDatum::List {
252 name_attributes,
253 delimiter,
254 name,
255 } => MailboxDatum::List {
256 name_attributes: name_attributes
257 .into_iter()
258 .map(|named_attribute| named_attribute.into_owned())
259 .collect(),
260 delimiter: delimiter.map(to_owned_cow),
261 name: to_owned_cow(name),
262 },
263 MailboxDatum::Search(seqs) => MailboxDatum::Search(seqs),
264 MailboxDatum::Sort(seqs) => MailboxDatum::Sort(seqs),
265 MailboxDatum::Status { mailbox, status } => MailboxDatum::Status {
266 mailbox: to_owned_cow(mailbox),
267 status,
268 },
269 MailboxDatum::Recent(seq) => MailboxDatum::Recent(seq),
270 MailboxDatum::MetadataSolicited { mailbox, values } => {
271 MailboxDatum::MetadataSolicited {
272 mailbox: to_owned_cow(mailbox),
273 values,
274 }
275 }
276 MailboxDatum::MetadataUnsolicited { mailbox, values } => {
277 MailboxDatum::MetadataUnsolicited {
278 mailbox: to_owned_cow(mailbox),
279 values: values.into_iter().map(to_owned_cow).collect(),
280 }
281 }
282 MailboxDatum::GmailLabels(labels) => {
283 MailboxDatum::GmailLabels(labels.into_iter().map(to_owned_cow).collect())
284 }
285 MailboxDatum::GmailMsgId(msgid) => MailboxDatum::GmailMsgId(msgid),
286 MailboxDatum::GmailThrId(thrid) => MailboxDatum::GmailThrId(thrid),
287 }
288 }
289}
290
291#[derive(Debug, Eq, PartialEq, Hash)]
292pub enum Capability<'a> {
293 Imap4rev1,
294 Auth(Cow<'a, str>),
295 Atom(Cow<'a, str>),
296}
297
298impl<'a> Capability<'a> {
299 pub fn into_owned(self) -> Capability<'static> {
300 match self {
301 Capability::Imap4rev1 => Capability::Imap4rev1,
302 Capability::Auth(v) => Capability::Auth(to_owned_cow(v)),
303 Capability::Atom(v) => Capability::Atom(to_owned_cow(v)),
304 }
305 }
306}
307
308#[derive(Debug, Eq, PartialEq)]
309#[non_exhaustive]
310pub enum Attribute {
311 Body,
312 Envelope,
313 Flags,
314 InternalDate,
315 ModSeq, Rfc822,
317 Rfc822Size,
318 Rfc822Text,
319 Uid,
320 GmailLabels,
322 GmailMsgId,
323 GmailThrId,
324}
325
326#[derive(Debug, Eq, PartialEq)]
327pub enum MessageSection {
328 Header,
329 Mime,
330 Text,
331}
332
333#[derive(Debug, Eq, PartialEq)]
334pub enum SectionPath {
335 Full(MessageSection),
336 Part(Vec<u32>, Option<MessageSection>),
337}
338
339#[allow(clippy::large_enum_variant)]
340#[derive(Debug, Eq, PartialEq)]
341#[non_exhaustive]
342pub enum AttributeValue<'a> {
343 BodySection {
344 section: Option<SectionPath>,
345 index: Option<u32>,
346 data: Option<Cow<'a, [u8]>>,
347 },
348 BodyStructure(BodyStructure<'a>),
349 Envelope(Box<Envelope<'a>>),
350 Flags(Vec<Cow<'a, str>>),
351 InternalDate(Cow<'a, str>),
352 ModSeq(u64), Rfc822(Option<Cow<'a, [u8]>>),
354 Rfc822Header(Option<Cow<'a, [u8]>>),
355 Rfc822Size(u32),
356 Rfc822Text(Option<Cow<'a, [u8]>>),
357 Uid(u32),
358 GmailLabels(Vec<Cow<'a, str>>),
360 GmailMsgId(u64),
361 GmailThrId(u64),
362}
363
364impl<'a> AttributeValue<'a> {
365 pub fn into_owned(self) -> AttributeValue<'static> {
366 match self {
367 AttributeValue::BodySection {
368 section,
369 index,
370 data,
371 } => AttributeValue::BodySection {
372 section,
373 index,
374 data: data.map(to_owned_cow),
375 },
376 AttributeValue::BodyStructure(body) => AttributeValue::BodyStructure(body.into_owned()),
377 AttributeValue::Envelope(e) => AttributeValue::Envelope(Box::new(e.into_owned())),
378 AttributeValue::Flags(v) => {
379 AttributeValue::Flags(v.into_iter().map(to_owned_cow).collect())
380 }
381 AttributeValue::InternalDate(v) => AttributeValue::InternalDate(to_owned_cow(v)),
382 AttributeValue::ModSeq(v) => AttributeValue::ModSeq(v),
383 AttributeValue::Rfc822(v) => AttributeValue::Rfc822(v.map(to_owned_cow)),
384 AttributeValue::Rfc822Header(v) => AttributeValue::Rfc822Header(v.map(to_owned_cow)),
385 AttributeValue::Rfc822Size(v) => AttributeValue::Rfc822Size(v),
386 AttributeValue::Rfc822Text(v) => AttributeValue::Rfc822Text(v.map(to_owned_cow)),
387 AttributeValue::Uid(v) => AttributeValue::Uid(v),
388 AttributeValue::GmailLabels(v) => {
389 AttributeValue::GmailLabels(v.into_iter().map(to_owned_cow).collect())
390 }
391 AttributeValue::GmailMsgId(v) => AttributeValue::GmailMsgId(v),
392 AttributeValue::GmailThrId(v) => AttributeValue::GmailThrId(v),
393 }
394 }
395}
396
397#[allow(clippy::large_enum_variant)]
398#[derive(Debug, Eq, PartialEq)]
399pub enum BodyStructure<'a> {
400 Basic {
401 common: BodyContentCommon<'a>,
402 other: BodyContentSinglePart<'a>,
403 extension: Option<BodyExtension<'a>>,
404 },
405 Text {
406 common: BodyContentCommon<'a>,
407 other: BodyContentSinglePart<'a>,
408 lines: u32,
409 extension: Option<BodyExtension<'a>>,
410 },
411 Message {
412 common: BodyContentCommon<'a>,
413 other: BodyContentSinglePart<'a>,
414 envelope: Envelope<'a>,
415 body: Box<BodyStructure<'a>>,
416 lines: u32,
417 extension: Option<BodyExtension<'a>>,
418 },
419 Multipart {
420 common: BodyContentCommon<'a>,
421 bodies: Vec<BodyStructure<'a>>,
422 extension: Option<BodyExtension<'a>>,
423 },
424}
425
426impl<'a> BodyStructure<'a> {
427 pub fn into_owned(self) -> BodyStructure<'static> {
428 match self {
429 BodyStructure::Basic {
430 common,
431 other,
432 extension,
433 } => BodyStructure::Basic {
434 common: common.into_owned(),
435 other: other.into_owned(),
436 extension: extension.map(|v| v.into_owned()),
437 },
438 BodyStructure::Text {
439 common,
440 other,
441 lines,
442 extension,
443 } => BodyStructure::Text {
444 common: common.into_owned(),
445 other: other.into_owned(),
446 lines,
447 extension: extension.map(|v| v.into_owned()),
448 },
449 BodyStructure::Message {
450 common,
451 other,
452 envelope,
453 body,
454 lines,
455 extension,
456 } => BodyStructure::Message {
457 common: common.into_owned(),
458 other: other.into_owned(),
459 envelope: envelope.into_owned(),
460 body: Box::new(body.into_owned()),
461 lines,
462 extension: extension.map(|v| v.into_owned()),
463 },
464 BodyStructure::Multipart {
465 common,
466 bodies,
467 extension,
468 } => BodyStructure::Multipart {
469 common: common.into_owned(),
470 bodies: bodies.into_iter().map(|v| v.into_owned()).collect(),
471 extension: extension.map(|v| v.into_owned()),
472 },
473 }
474 }
475}
476
477#[derive(Debug, Eq, PartialEq)]
478pub struct BodyContentCommon<'a> {
479 pub ty: ContentType<'a>,
480 pub disposition: Option<ContentDisposition<'a>>,
481 pub language: Option<Vec<Cow<'a, str>>>,
482 pub location: Option<Cow<'a, str>>,
483}
484
485impl<'a> BodyContentCommon<'a> {
486 pub fn into_owned(self) -> BodyContentCommon<'static> {
487 BodyContentCommon {
488 ty: self.ty.into_owned(),
489 disposition: self.disposition.map(|v| v.into_owned()),
490 language: self
491 .language
492 .map(|v| v.into_iter().map(to_owned_cow).collect()),
493 location: self.location.map(to_owned_cow),
494 }
495 }
496}
497
498#[derive(Debug, Eq, PartialEq)]
499pub struct BodyContentSinglePart<'a> {
500 pub id: Option<Cow<'a, str>>,
501 pub md5: Option<Cow<'a, str>>,
502 pub description: Option<Cow<'a, str>>,
503 pub transfer_encoding: ContentEncoding<'a>,
504 pub octets: u32,
505}
506
507impl<'a> BodyContentSinglePart<'a> {
508 pub fn into_owned(self) -> BodyContentSinglePart<'static> {
509 BodyContentSinglePart {
510 id: self.id.map(to_owned_cow),
511 md5: self.md5.map(to_owned_cow),
512 description: self.description.map(to_owned_cow),
513 transfer_encoding: self.transfer_encoding.into_owned(),
514 octets: self.octets,
515 }
516 }
517}
518
519#[derive(Debug, Eq, PartialEq)]
520pub struct ContentType<'a> {
521 pub ty: Cow<'a, str>,
522 pub subtype: Cow<'a, str>,
523 pub params: BodyParams<'a>,
524}
525
526impl<'a> ContentType<'a> {
527 pub fn into_owned(self) -> ContentType<'static> {
528 ContentType {
529 ty: to_owned_cow(self.ty),
530 subtype: to_owned_cow(self.subtype),
531 params: body_param_owned(self.params),
532 }
533 }
534}
535
536#[derive(Debug, Eq, PartialEq)]
537pub struct ContentDisposition<'a> {
538 pub ty: Cow<'a, str>,
539 pub params: BodyParams<'a>,
540}
541
542impl<'a> ContentDisposition<'a> {
543 pub fn into_owned(self) -> ContentDisposition<'static> {
544 ContentDisposition {
545 ty: to_owned_cow(self.ty),
546 params: body_param_owned(self.params),
547 }
548 }
549}
550
551#[derive(Debug, Eq, PartialEq)]
552pub enum ContentEncoding<'a> {
553 SevenBit,
554 EightBit,
555 Binary,
556 Base64,
557 QuotedPrintable,
558 Other(Cow<'a, str>),
559}
560
561impl<'a> ContentEncoding<'a> {
562 pub fn into_owned(self) -> ContentEncoding<'static> {
563 match self {
564 ContentEncoding::SevenBit => ContentEncoding::SevenBit,
565 ContentEncoding::EightBit => ContentEncoding::EightBit,
566 ContentEncoding::Binary => ContentEncoding::Binary,
567 ContentEncoding::Base64 => ContentEncoding::Base64,
568 ContentEncoding::QuotedPrintable => ContentEncoding::QuotedPrintable,
569 ContentEncoding::Other(v) => ContentEncoding::Other(to_owned_cow(v)),
570 }
571 }
572}
573
574#[derive(Debug, Eq, PartialEq)]
575pub enum BodyExtension<'a> {
576 Num(u32),
577 Str(Option<Cow<'a, str>>),
578 List(Vec<BodyExtension<'a>>),
579}
580
581impl<'a> BodyExtension<'a> {
582 pub fn into_owned(self) -> BodyExtension<'static> {
583 match self {
584 BodyExtension::Num(v) => BodyExtension::Num(v),
585 BodyExtension::Str(v) => BodyExtension::Str(v.map(to_owned_cow)),
586 BodyExtension::List(v) => {
587 BodyExtension::List(v.into_iter().map(|v| v.into_owned()).collect())
588 }
589 }
590 }
591}
592
593pub type BodyParams<'a> = Option<Vec<(Cow<'a, str>, Cow<'a, str>)>>;
594
595fn body_param_owned(v: BodyParams<'_>) -> BodyParams<'static> {
596 v.map(|v| {
597 v.into_iter()
598 .map(|(k, v)| (to_owned_cow(k), to_owned_cow(v)))
599 .collect()
600 })
601}
602
603#[derive(Debug, Eq, PartialEq)]
607pub struct Envelope<'a> {
608 pub date: Option<Cow<'a, [u8]>>,
609 pub subject: Option<Cow<'a, [u8]>>,
610 pub from: Option<Vec<Address<'a>>>,
612 pub sender: Option<Vec<Address<'a>>>,
614 pub reply_to: Option<Vec<Address<'a>>>,
616 pub to: Option<Vec<Address<'a>>>,
617 pub cc: Option<Vec<Address<'a>>>,
618 pub bcc: Option<Vec<Address<'a>>>,
619 pub in_reply_to: Option<Cow<'a, [u8]>>,
620 pub message_id: Option<Cow<'a, [u8]>>,
621}
622
623impl<'a> Envelope<'a> {
624 pub fn into_owned(self) -> Envelope<'static> {
625 Envelope {
626 date: self.date.map(to_owned_cow),
627 subject: self.subject.map(to_owned_cow),
628 from: self
629 .from
630 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
631 sender: self
632 .sender
633 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
634 reply_to: self
635 .reply_to
636 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
637 to: self
638 .to
639 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
640 cc: self
641 .cc
642 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
643 bcc: self
644 .bcc
645 .map(|v| v.into_iter().map(|v| v.into_owned()).collect()),
646 in_reply_to: self.in_reply_to.map(to_owned_cow),
647 message_id: self.message_id.map(to_owned_cow),
648 }
649 }
650}
651
652#[derive(Debug, Eq, PartialEq)]
653pub struct Address<'a> {
654 pub name: Option<Cow<'a, [u8]>>,
655 pub adl: Option<Cow<'a, [u8]>>,
656 pub mailbox: Option<Cow<'a, [u8]>>,
657 pub host: Option<Cow<'a, [u8]>>,
658}
659
660impl<'a> Address<'a> {
661 pub fn into_owned(self) -> Address<'static> {
662 Address {
663 name: self.name.map(to_owned_cow),
664 adl: self.adl.map(to_owned_cow),
665 mailbox: self.mailbox.map(to_owned_cow),
666 host: self.host.map(to_owned_cow),
667 }
668 }
669}
670
671#[derive(Clone, Debug, Eq, PartialEq)]
672pub struct RequestId(pub String);
673
674impl RequestId {
675 pub fn as_bytes(&self) -> &[u8] {
676 self.0.as_bytes()
677 }
678}
679
680#[derive(Clone, Copy, Debug, Eq, PartialEq)]
681pub enum State {
682 NotAuthenticated,
683 Authenticated,
684 Selected,
685 Logout,
686}
687
688pub struct BodyFields<'a> {
691 pub param: BodyParams<'a>,
692 pub id: Option<Cow<'a, str>>,
693 pub description: Option<Cow<'a, str>>,
694 pub transfer_encoding: ContentEncoding<'a>,
695 pub octets: u32,
696}
697
698impl<'a> BodyFields<'a> {
699 pub fn into_owned(self) -> BodyFields<'static> {
700 BodyFields {
701 param: body_param_owned(self.param),
702 id: self.id.map(to_owned_cow),
703 description: self.description.map(to_owned_cow),
704 transfer_encoding: self.transfer_encoding.into_owned(),
705 octets: self.octets,
706 }
707 }
708}
709
710pub struct BodyExt1Part<'a> {
711 pub md5: Option<Cow<'a, str>>,
712 pub disposition: Option<ContentDisposition<'a>>,
713 pub language: Option<Vec<Cow<'a, str>>>,
714 pub location: Option<Cow<'a, str>>,
715 pub extension: Option<BodyExtension<'a>>,
716}
717
718impl<'a> BodyExt1Part<'a> {
719 pub fn into_owned(self) -> BodyExt1Part<'static> {
720 BodyExt1Part {
721 md5: self.md5.map(to_owned_cow),
722 disposition: self.disposition.map(|v| v.into_owned()),
723 language: self
724 .language
725 .map(|v| v.into_iter().map(to_owned_cow).collect()),
726 location: self.location.map(to_owned_cow),
727 extension: self.extension.map(|v| v.into_owned()),
728 }
729 }
730}
731
732pub struct BodyExtMPart<'a> {
733 pub param: BodyParams<'a>,
734 pub disposition: Option<ContentDisposition<'a>>,
735 pub language: Option<Vec<Cow<'a, str>>>,
736 pub location: Option<Cow<'a, str>>,
737 pub extension: Option<BodyExtension<'a>>,
738}
739
740impl<'a> BodyExtMPart<'a> {
741 pub fn into_owned(self) -> BodyExtMPart<'static> {
742 BodyExtMPart {
743 param: body_param_owned(self.param),
744 disposition: self.disposition.map(|v| v.into_owned()),
745 language: self
746 .language
747 .map(|v| v.into_iter().map(to_owned_cow).collect()),
748 location: self.location.map(to_owned_cow),
749 extension: self.extension.map(|v| v.into_owned()),
750 }
751 }
752}
753
754#[derive(Debug, Eq, PartialEq, Clone)]
760#[non_exhaustive]
761pub enum NameAttribute<'a> {
762 NoInferiors,
768 NoSelect,
772 Marked,
778 Unmarked,
783 All,
790 Archive,
797 Drafts,
806 Flagged,
813 Junk,
820 Sent,
827 Trash,
839 Extension(Cow<'a, str>),
842}
843
844impl<'a> NameAttribute<'a> {
845 pub fn into_owned(self) -> NameAttribute<'static> {
846 match self {
847 NameAttribute::NoInferiors => NameAttribute::NoInferiors,
849 NameAttribute::NoSelect => NameAttribute::NoSelect,
850 NameAttribute::Marked => NameAttribute::Marked,
851 NameAttribute::Unmarked => NameAttribute::Unmarked,
852 NameAttribute::All => NameAttribute::All,
854 NameAttribute::Archive => NameAttribute::Archive,
855 NameAttribute::Drafts => NameAttribute::Drafts,
856 NameAttribute::Flagged => NameAttribute::Flagged,
857 NameAttribute::Junk => NameAttribute::Junk,
858 NameAttribute::Sent => NameAttribute::Sent,
859 NameAttribute::Trash => NameAttribute::Trash,
860 NameAttribute::Extension(s) => NameAttribute::Extension(to_owned_cow(s)),
862 }
863 }
864}
865
866#[derive(Debug, Eq, PartialEq, Hash, Clone)]
870pub enum QuotaResourceName<'a> {
871 Storage,
873 Message,
875 Atom(Cow<'a, str>),
876}
877
878impl<'a> QuotaResourceName<'a> {
879 pub fn into_owned(self) -> QuotaResourceName<'static> {
880 match self {
881 QuotaResourceName::Message => QuotaResourceName::Message,
882 QuotaResourceName::Storage => QuotaResourceName::Storage,
883 QuotaResourceName::Atom(v) => QuotaResourceName::Atom(to_owned_cow(v)),
884 }
885 }
886}
887
888#[derive(Debug, Eq, PartialEq, Hash, Clone)]
890pub struct QuotaResource<'a> {
891 pub name: QuotaResourceName<'a>,
892 pub usage: u64,
894 pub limit: u64,
896}
897
898impl<'a> QuotaResource<'a> {
899 pub fn into_owned(self) -> QuotaResource<'static> {
900 QuotaResource {
901 name: self.name.into_owned(),
902 usage: self.usage,
903 limit: self.limit,
904 }
905 }
906}
907
908#[derive(Debug, Eq, PartialEq, Hash, Clone)]
910pub struct Quota<'a> {
911 pub root_name: Cow<'a, str>,
913 pub resources: Vec<QuotaResource<'a>>,
914}
915
916impl<'a> Quota<'a> {
917 pub fn into_owned(self) -> Quota<'static> {
918 Quota {
919 root_name: to_owned_cow(self.root_name),
920 resources: self.resources.into_iter().map(|r| r.into_owned()).collect(),
921 }
922 }
923}
924
925#[derive(Debug, Eq, PartialEq, Hash, Clone)]
927pub struct QuotaRoot<'a> {
928 pub mailbox_name: Cow<'a, str>,
930 pub quota_root_names: Vec<Cow<'a, str>>,
932}
933
934impl<'a> QuotaRoot<'a> {
935 pub fn into_owned(self) -> QuotaRoot<'static> {
936 QuotaRoot {
937 mailbox_name: to_owned_cow(self.mailbox_name),
938 quota_root_names: self
939 .quota_root_names
940 .into_iter()
941 .map(to_owned_cow)
942 .collect(),
943 }
944 }
945}
946
947#[cfg(test)]
948mod tests {
949 use super::*;
950
951 #[test]
954 fn test_name_attribute_into_owned() {
955 let name_attributes = [
956 NameAttribute::NoInferiors,
958 NameAttribute::NoSelect,
959 NameAttribute::Marked,
960 NameAttribute::Unmarked,
961 NameAttribute::All,
963 NameAttribute::Archive,
964 NameAttribute::Drafts,
965 NameAttribute::Flagged,
966 NameAttribute::Junk,
967 NameAttribute::Sent,
968 NameAttribute::Trash,
969 NameAttribute::Extension(Cow::Borrowed("Foobar")),
971 ];
972
973 for name_attribute in name_attributes {
974 let owned_name_attribute = name_attribute.clone().into_owned();
975 assert_eq!(name_attribute, owned_name_attribute);
976 }
977 }
978}