Access headers as key/values #24
5 changed files with 80 additions and 13 deletions
|
@ -1,3 +1,4 @@
|
|||
use std::fmt;
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_while1},
|
||||
|
@ -11,13 +12,21 @@ use nom::{
|
|||
use crate::text::whitespace::{foldable_line, obs_crlf};
|
||||
use crate::text::misc_token::unstructured;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub struct Kv2<'a>(pub &'a [u8], pub &'a [u8]);
|
||||
impl<'a> From<(&'a [u8], &'a [u8])> for Kv2<'a> {
|
||||
fn from(pair: (&'a [u8], &'a [u8])) -> Self {
|
||||
Self(pair.0, pair.1)
|
||||
}
|
||||
}
|
||||
impl<'a> fmt::Debug for Kv2<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("header::Kv2")
|
||||
.field(&String::from_utf8_lossy(self.0))
|
||||
.field(&String::from_utf8_lossy(self.1))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Field<'a> {
|
||||
|
|
|
@ -10,6 +10,7 @@ pub mod mechanism;
|
|||
/// Content-Type representation
|
||||
pub mod r#type;
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::imf::identification::MessageID;
|
||||
|
@ -55,15 +56,27 @@ impl<'a, T: WithDefaultType> From<AnyMIMEWithDefault<'a, T>> for AnyMIME<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Default, Clone)]
|
||||
#[derive(PartialEq, Default, Clone)]
|
||||
pub struct NaiveMIME<'a> {
|
||||
pub ctype: Option<NaiveType<'a>>,
|
||||
pub transfer_encoding: Mechanism<'a>,
|
||||
pub id: Option<MessageID<'a>>,
|
||||
pub description: Option<Unstructured<'a>>,
|
||||
pub fields: Vec<header::Field<'a>>,
|
||||
pub kv: Vec<header::Field<'a>>,
|
||||
pub raw: &'a [u8],
|
||||
}
|
||||
impl<'a> fmt::Debug for NaiveMIME<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("NaiveMime")
|
||||
.field("ctype", &self.ctype)
|
||||
.field("transfer_encoding", &self.transfer_encoding)
|
||||
.field("id", &self.id)
|
||||
.field("description", &self.description)
|
||||
.field("kv", &self.kv)
|
||||
.field("raw", &String::from_utf8_lossy(self.raw))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<Content<'a>> for NaiveMIME<'a> {
|
||||
fn from_iter<I: IntoIterator<Item = Content<'a>>>(it: I) -> Self {
|
||||
|
@ -83,8 +96,8 @@ impl<'a> FromIterator<Content<'a>> for NaiveMIME<'a> {
|
|||
}
|
||||
|
||||
impl<'a> NaiveMIME<'a> {
|
||||
pub fn with_fields(mut self, fields: Vec<header::Field<'a>>) -> Self {
|
||||
self.fields = fields; self
|
||||
pub fn with_kv(mut self, fields: Vec<header::Field<'a>>) -> Self {
|
||||
self.kv = fields; self
|
||||
}
|
||||
pub fn with_raw(mut self, raw: &'a [u8]) -> Self {
|
||||
self.raw = raw; self
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt;
|
||||
use nom::{
|
||||
bytes::complete::tag,
|
||||
combinator::{map, opt},
|
||||
|
@ -12,12 +13,21 @@ use crate::text::words::mime_atom;
|
|||
use crate::mime::{AnyMIME, MIME, NaiveMIME};
|
||||
|
||||
// --------- NAIVE TYPE
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub struct NaiveType<'a> {
|
||||
pub main: &'a [u8],
|
||||
pub sub: &'a [u8],
|
||||
pub params: Vec<Parameter<'a>>,
|
||||
}
|
||||
impl<'a> fmt::Debug for NaiveType<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("mime::NaiveType")
|
||||
.field("main", &String::from_utf8_lossy(self.main))
|
||||
.field("sub", &String::from_utf8_lossy(self.sub))
|
||||
.field("params", &self.params)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl<'a> NaiveType<'a> {
|
||||
pub fn to_type(&self) -> AnyType {
|
||||
self.into()
|
||||
|
@ -30,11 +40,20 @@ pub fn naive_type(input: &[u8]) -> IResult<&[u8], NaiveType> {
|
|||
)(input)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub struct Parameter<'a> {
|
||||
pub name: &'a [u8],
|
||||
pub value: MIMEWord<'a>,
|
||||
}
|
||||
impl<'a> fmt::Debug for Parameter<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("mime::Parameter")
|
||||
.field("name", &String::from_utf8_lossy(self.name))
|
||||
.field("value", &self.value)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parameter(input: &[u8]) -> IResult<&[u8], Parameter> {
|
||||
map(
|
||||
tuple((mime_atom, tag(b"="), mime_word)),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt;
|
||||
use nom::IResult;
|
||||
|
||||
use crate::header;
|
||||
|
@ -8,13 +9,23 @@ use crate::text::boundary::{boundary, Delimiter};
|
|||
use crate::pointers;
|
||||
|
||||
//--- Multipart
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(PartialEq)]
|
||||
pub struct Multipart<'a> {
|
||||
pub mime: mime::MIME<'a, mime::r#type::Multipart>,
|
||||
pub children: Vec<AnyPart<'a>>,
|
||||
pub raw_part_inner: &'a [u8],
|
||||
pub raw_part_outer: &'a [u8],
|
||||
}
|
||||
impl<'a> fmt::Debug for Multipart<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("part::Multipart")
|
||||
.field("mime", &self.mime)
|
||||
.field("children", &self.children)
|
||||
.field("raw_part_inner", &String::from_utf8_lossy(self.raw_part_inner))
|
||||
.field("raw_part_outer", &String::from_utf8_lossy(self.raw_part_outer))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl<'a> Multipart<'a> {
|
||||
pub fn preamble(&self) -> &'a [u8] {
|
||||
pointers::parsed(self.raw_part_outer, self.raw_part_inner)
|
||||
|
@ -83,7 +94,7 @@ pub fn multipart<'a>(
|
|||
.collect::<mime::NaiveMIME>();
|
||||
|
||||
let mime = mime
|
||||
.with_fields(fields)
|
||||
.with_kv(fields)
|
||||
.with_raw(raw_hdrs);
|
||||
|
||||
(input_eom, mime)
|
||||
|
@ -113,7 +124,7 @@ pub fn multipart<'a>(
|
|||
|
||||
//--- Message
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(PartialEq)]
|
||||
pub struct Message<'a> {
|
||||
pub mime: mime::MIME<'a, mime::r#type::DeductibleMessage>,
|
||||
pub imf: imf::Imf<'a>,
|
||||
|
@ -123,6 +134,18 @@ pub struct Message<'a> {
|
|||
pub raw_headers: &'a [u8],
|
||||
pub raw_body: &'a [u8],
|
||||
}
|
||||
impl<'a> fmt::Debug for Message<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("part::Message")
|
||||
.field("mime", &self.mime)
|
||||
.field("imf", &self.imf)
|
||||
.field("child", &self.child)
|
||||
.field("raw_part", &String::from_utf8_lossy(self.raw_part))
|
||||
.field("raw_headers", &String::from_utf8_lossy(self.raw_headers))
|
||||
.field("raw_body", &String::from_utf8_lossy(self.raw_body))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message<'a>(
|
||||
m: mime::MIME<'a, mime::r#type::DeductibleMessage>,
|
||||
|
@ -142,7 +165,7 @@ pub fn message<'a>(
|
|||
let (naive_mime, imf) = part::field::split_and_build(&headers);
|
||||
|
||||
// interpret headers to choose a mime type
|
||||
let in_mime = naive_mime.with_fields(headers).with_raw(raw_headers).to_interpreted::<mime::WithGenericDefault>().into();
|
||||
let in_mime = naive_mime.with_kv(headers).with_raw(raw_headers).to_interpreted::<mime::WithGenericDefault>().into();
|
||||
//---------------
|
||||
|
||||
// parse a part following this mime specification
|
||||
|
@ -256,6 +279,9 @@ It DOES end with a linebreak.
|
|||
]
|
||||
}),
|
||||
raw: &b"Content-type: text/plain; charset=us-ascii\n\n"[..],
|
||||
kv: vec![
|
||||
header::Field::Good(header::Kv2(&b"Content-type"[..], &b"text/plain; charset=us-ascii"[..]))
|
||||
],
|
||||
..mime::NaiveMIME::default()
|
||||
},
|
||||
},
|
||||
|
|
|
@ -14,7 +14,7 @@ impl<'a> fmt::Debug for Text<'a> {
|
|||
.field("mime", &self.mime)
|
||||
.field(
|
||||
"body",
|
||||
&format_args!("\"{}\"", String::from_utf8_lossy(self.body)),
|
||||
&String::from_utf8_lossy(self.body),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ impl<'a> fmt::Debug for Binary<'a> {
|
|||
.field("mime", &self.mime)
|
||||
.field(
|
||||
"body",
|
||||
&format_args!("\"{}\"", String::from_utf8_lossy(self.body)),
|
||||
&String::from_utf8_lossy(self.body),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue