Skip to content

Commit 54da551

Browse files
authored
Cows! Cows everywhere! (#115)
1 parent 27e26f7 commit 54da551

File tree

10 files changed

+471
-161
lines changed

10 files changed

+471
-161
lines changed

imap-proto/src/parser/rfc3501/body.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use nom::{
77
sequence::{delimited, preceded, tuple},
88
IResult,
99
};
10+
use std::borrow::Cow;
1011

1112
use crate::{parser::core::*, types::*};
1213

@@ -65,7 +66,7 @@ pub fn msg_att_body_section(i: &[u8]) -> IResult<&[u8], AttributeValue> {
6566
|(_, section, index, _, data)| AttributeValue::BodySection {
6667
section,
6768
index,
68-
data,
69+
data: data.map(Cow::Borrowed),
6970
},
7071
)(i)
7172
}

imap-proto/src/parser/rfc3501/body_structure.rs

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use nom::{
77
sequence::{delimited, preceded, tuple},
88
IResult,
99
};
10+
use std::borrow::Cow;
1011

1112
use crate::{
1213
parser::{core::*, rfc3501::envelope},
@@ -35,8 +36,8 @@ fn body_fields(i: &[u8]) -> IResult<&[u8], BodyFields> {
3536
i,
3637
BodyFields {
3738
param,
38-
id,
39-
description,
39+
id: id.map(Cow::Borrowed),
40+
description: description.map(Cow::Borrowed),
4041
transfer_encoding,
4142
octets,
4243
},
@@ -60,10 +61,10 @@ fn body_ext_1part(i: &[u8]) -> IResult<&[u8], BodyExt1Part> {
6061
Ok((
6162
i,
6263
BodyExt1Part {
63-
md5,
64+
md5: md5.map(Cow::Borrowed),
6465
disposition,
6566
language,
66-
location,
67+
location: location.map(Cow::Borrowed),
6768
extension,
6869
},
6970
))
@@ -88,7 +89,7 @@ fn body_ext_mpart(i: &[u8]) -> IResult<&[u8], BodyExtMPart> {
8889
param,
8990
disposition,
9091
language,
91-
location,
92+
location: location.map(Cow::Borrowed),
9293
extension,
9394
},
9495
))
@@ -109,15 +110,20 @@ fn body_encoding(i: &[u8]) -> IResult<&[u8], ContentEncoding> {
109110
)),
110111
char('"'),
111112
),
112-
map(string_utf8, |enc| ContentEncoding::Other(enc)),
113+
map(string_utf8, |enc| {
114+
ContentEncoding::Other(Cow::Borrowed(enc))
115+
}),
113116
))(i)
114117
}
115118

116-
fn body_lang(i: &[u8]) -> IResult<&[u8], Option<Vec<&str>>> {
119+
fn body_lang(i: &[u8]) -> IResult<&[u8], Option<Vec<Cow<'_, str>>>> {
117120
alt((
118121
// body language seems to refer to RFC 3066 language tags, which should be ASCII-only
119-
map(nstring_utf8, |v| v.map(|s| vec![s])),
120-
map(parenthesized_nonempty_list(string_utf8), Option::from),
122+
map(nstring_utf8, |v| v.map(|s| vec![Cow::Borrowed(s)])),
123+
map(
124+
parenthesized_nonempty_list(map(string_utf8, Cow::Borrowed)),
125+
Option::from,
126+
),
121127
))(i)
122128
}
123129

@@ -127,7 +133,7 @@ fn body_param(i: &[u8]) -> IResult<&[u8], BodyParams> {
127133
map(
128134
parenthesized_nonempty_list(map(
129135
tuple((string_utf8, tag(" "), string_utf8)),
130-
|(key, _, val)| (key, val),
136+
|(key, _, val)| (Cow::Borrowed(key), Cow::Borrowed(val)),
131137
)),
132138
Option::from,
133139
),
@@ -139,7 +145,7 @@ fn body_extension(i: &[u8]) -> IResult<&[u8], BodyExtension> {
139145
map(number, BodyExtension::Num),
140146
// Cannot find documentation on character encoding for body extension values.
141147
// So far, assuming UTF-8 seems fine, please report if you run into issues here.
142-
map(nstring_utf8, BodyExtension::Str),
148+
map(nstring_utf8, |v| BodyExtension::Str(v.map(Cow::Borrowed))),
143149
map(
144150
parenthesized_nonempty_list(body_extension),
145151
BodyExtension::List,
@@ -152,7 +158,12 @@ fn body_disposition(i: &[u8]) -> IResult<&[u8], Option<ContentDisposition>> {
152158
map(nil, |_| None),
153159
paren_delimited(map(
154160
tuple((string_utf8, tag(" "), body_param)),
155-
|(ty, _, params)| Some(ContentDisposition { ty, params }),
161+
|(ty, _, params)| {
162+
Some(ContentDisposition {
163+
ty: Cow::Borrowed(ty),
164+
params,
165+
})
166+
},
156167
)),
157168
))(i)
158169
}
@@ -170,8 +181,8 @@ fn body_type_basic(i: &[u8]) -> IResult<&[u8], BodyStructure> {
170181
|(ty, _, subtype, _, fields, ext)| BodyStructure::Basic {
171182
common: BodyContentCommon {
172183
ty: ContentType {
173-
ty,
174-
subtype,
184+
ty: Cow::Borrowed(ty),
185+
subtype: Cow::Borrowed(subtype),
175186
params: fields.param,
176187
},
177188
disposition: ext.disposition,
@@ -205,8 +216,8 @@ fn body_type_text(i: &[u8]) -> IResult<&[u8], BodyStructure> {
205216
|(_, _, subtype, _, fields, _, lines, ext)| BodyStructure::Text {
206217
common: BodyContentCommon {
207218
ty: ContentType {
208-
ty: "TEXT",
209-
subtype,
219+
ty: Cow::Borrowed("TEXT"),
220+
subtype: Cow::Borrowed(subtype),
210221
params: fields.param,
211222
},
212223
disposition: ext.disposition,
@@ -243,8 +254,8 @@ fn body_type_message(i: &[u8]) -> IResult<&[u8], BodyStructure> {
243254
|(_, _, fields, _, envelope, _, body, _, lines, ext)| BodyStructure::Message {
244255
common: BodyContentCommon {
245256
ty: ContentType {
246-
ty: "MESSAGE",
247-
subtype: "RFC822",
257+
ty: Cow::Borrowed("MESSAGE"),
258+
subtype: Cow::Borrowed("RFC822"),
248259
params: fields.param,
249260
},
250261
disposition: ext.disposition,
@@ -272,8 +283,8 @@ fn body_type_multipart(i: &[u8]) -> IResult<&[u8], BodyStructure> {
272283
|(bodies, _, subtype, ext)| BodyStructure::Multipart {
273284
common: BodyContentCommon {
274285
ty: ContentType {
275-
ty: "MULTIPART",
276-
subtype,
286+
ty: Cow::Borrowed("MULTIPART"),
287+
subtype: Cow::Borrowed(subtype),
277288
params: ext.param,
278289
},
279290
disposition: ext.disposition,
@@ -310,9 +321,10 @@ mod tests {
310321

311322
// body-fld-param SP body-fld-id SP body-fld-desc SP body-fld-enc SP body-fld-octets
312323
const BODY_FIELDS: &str = r#"("foo" "bar") "id" "desc" "7BIT" 1337"#;
313-
const BODY_FIELD_PARAM_PAIR: (&str, &str) = ("foo", "bar");
314-
const BODY_FIELD_ID: Option<&str> = Some("id");
315-
const BODY_FIELD_DESC: Option<&str> = Some("desc");
324+
const BODY_FIELD_PARAM_PAIR: (Cow<'_, str>, Cow<'_, str>) =
325+
(Cow::Borrowed("foo"), Cow::Borrowed("bar"));
326+
const BODY_FIELD_ID: Option<Cow<'_, str>> = Some(Cow::Borrowed("id"));
327+
const BODY_FIELD_DESC: Option<Cow<'_, str>> = Some(Cow::Borrowed("desc"));
316328
const BODY_FIELD_ENC: ContentEncoding = ContentEncoding::SevenBit;
317329
const BODY_FIELD_OCTETS: u32 = 1337;
318330

@@ -322,8 +334,8 @@ mod tests {
322334
BodyStructure::Text {
323335
common: BodyContentCommon {
324336
ty: ContentType {
325-
ty: "TEXT",
326-
subtype: "PLAIN",
337+
ty: Cow::Borrowed("TEXT"),
338+
subtype: Cow::Borrowed("PLAIN"),
327339
params: Some(vec![BODY_FIELD_PARAM_PAIR]),
328340
},
329341
disposition: None,
@@ -350,7 +362,7 @@ mod tests {
350362
assert_matches!(
351363
body_param(br#"("foo" "bar")"#),
352364
Ok((EMPTY, Some(param))) => {
353-
assert_eq!(param, vec![("foo", "bar")]);
365+
assert_eq!(param, vec![(Cow::Borrowed("foo"), Cow::Borrowed("bar"))]);
354366
}
355367
);
356368
}
@@ -378,7 +390,7 @@ mod tests {
378390
fn test_body_extension_data() {
379391
assert_matches!(
380392
body_extension(br#""blah""#),
381-
Ok((EMPTY, BodyExtension::Str(Some("blah"))))
393+
Ok((EMPTY, BodyExtension::Str(Some(Cow::Borrowed("blah")))))
382394
);
383395

384396
assert_matches!(
@@ -389,7 +401,7 @@ mod tests {
389401
assert_matches!(
390402
body_extension(br#"("hello")"#),
391403
Ok((EMPTY, BodyExtension::List(list))) => {
392-
assert_eq!(list, vec![BodyExtension::Str(Some("hello"))]);
404+
assert_eq!(list, vec![BodyExtension::Str(Some(Cow::Borrowed("hello")))]);
393405
}
394406
);
395407

@@ -409,9 +421,9 @@ mod tests {
409421
body_disposition(br#"("attachment" ("FILENAME" "pages.pdf"))"#),
410422
Ok((EMPTY, Some(disposition))) => {
411423
assert_eq!(disposition, ContentDisposition {
412-
ty: "attachment",
424+
ty: Cow::Borrowed("attachment"),
413425
params: Some(vec![
414-
("FILENAME", "pages.pdf")
426+
(Cow::Borrowed("FILENAME"), Cow::Borrowed("pages.pdf"))
415427
])
416428
});
417429
}
@@ -453,13 +465,13 @@ mod tests {
453465
assert_eq!(basic, BodyStructure::Basic {
454466
common: BodyContentCommon {
455467
ty: ContentType {
456-
ty: "APPLICATION",
457-
subtype: "PDF",
458-
params: Some(vec![("NAME", "pages.pdf")])
468+
ty: Cow::Borrowed("APPLICATION"),
469+
subtype: Cow::Borrowed("PDF"),
470+
params: Some(vec![(Cow::Borrowed("NAME"), Cow::Borrowed("pages.pdf"))])
459471
},
460472
disposition: Some(ContentDisposition {
461-
ty: "attachment",
462-
params: Some(vec![("FILENAME", "pages.pdf")])
473+
ty: Cow::Borrowed("attachment"),
474+
params: Some(vec![(Cow::Borrowed("FILENAME"), Cow::Borrowed("pages.pdf"))])
463475
}),
464476
language: None,
465477
location: None,
@@ -507,8 +519,8 @@ mod tests {
507519
assert_eq!(multipart, BodyStructure::Multipart {
508520
common: BodyContentCommon {
509521
ty: ContentType {
510-
ty: "MULTIPART",
511-
subtype: "ALTERNATIVE",
522+
ty: Cow::Borrowed("MULTIPART"),
523+
subtype: Cow::Borrowed("ALTERNATIVE"),
512524
params: None
513525
},
514526
language: None,

0 commit comments

Comments
 (0)