1use bounded_static::ToStatic;
2#[cfg(feature = "tracing")]
3use tracing::warn;
4
5#[cfg(feature = "arbitrary")]
6use crate::fuzz_eq::FuzzEq;
7use crate::header;
8use crate::mime;
9use crate::print::{Formatter, Print};
10use crate::raw_input::RawInput;
11
12#[derive(Clone, Debug, PartialEq, ToStatic)]
15#[cfg_attr(feature = "arbitrary", derive(FuzzEq))]
16pub enum EntityField<'a> {
17 MIME {
18 f: mime::field::Field<'a>,
19 raw_body: RawInput<'a>,
20 },
21 Unstructured(header::Unstructured<'a>),
22}
23
24impl<'a> EntityField<'a> {
25 pub fn raw_name(&self) -> header::FieldName<'a> {
26 match self {
27 EntityField::MIME { f, .. } => f.raw_name(),
28 EntityField::Unstructured(u) => u.name.clone(),
29 }
30 }
31
32 pub fn raw_body(&self) -> RawInput<'a> {
33 match self {
34 EntityField::MIME { raw_body, .. } => raw_body.clone(),
35 EntityField::Unstructured(u) => u.raw_body.clone(),
36 }
37 }
38}
39
40impl<'a> Print for EntityField<'a> {
41 fn print(&self, fmt: &mut impl Formatter) {
42 match self {
43 EntityField::MIME { f, .. } => f.print(fmt),
44 EntityField::Unstructured(u) => u.print(fmt),
45 }
46 }
47}
48
49#[derive(Clone, Debug, PartialEq, ToStatic)]
51#[cfg_attr(feature = "arbitrary", derive(FuzzEq))]
52pub enum EntityEntry<'a> {
53 MIME {
54 e: mime::field::Entry,
55 raw_body: RawInput<'a>,
56 },
57 Unstructured(header::Unstructured<'a>),
58}
59
60#[derive(Debug, Default, PartialEq, ToStatic)]
63#[cfg_attr(feature = "arbitrary", derive(FuzzEq))]
64pub(crate) struct NaiveEntityFields<'a> {
65 pub mime: mime::NaiveMIME<'a>,
66 pub entries: Vec<EntityEntry<'a>>,
67}
68
69impl<'a> FromIterator<header::FieldRaw<'a>> for NaiveEntityFields<'a> {
70 #[cfg_attr(
71 feature = "tracing",
72 tracing::instrument(name = "EntityFields::from_iter", skip(it))
73 )]
74 fn from_iter<I: IntoIterator<Item = header::FieldRaw<'a>>>(it: I) -> Self {
75 let mut e: NaiveEntityFields<'a> = Default::default();
76 for f in it {
77 match mime::field::NaiveField::try_from(&f) {
78 Ok(mimef) => {
79 if let Some(entry) = e.mime.add_field(mimef) {
80 e.entries.push(EntityEntry::MIME {
81 e: entry,
82 raw_body: f.body.into(),
83 })
84 } else {
85 #[cfg(feature = "tracing-recover")]
87 warn!(field = ?f, "dropping conflicting MIME field");
88 }
89 continue;
90 }
91 Err(mime::field::InvalidField::Body) => {
92 #[cfg(feature = "tracing-unsupported")]
94 warn!(field = ?f, "dropping MIME field with an invalid body");
95 continue;
96 }
97 Err(mime::field::InvalidField::Name) => {
98 }
100 };
101
102 if let Some(u) = header::Unstructured::from_raw(&f) {
103 e.entries.push(EntityEntry::Unstructured(u));
104 } else {
105 #[cfg(feature = "tracing-unsupported")]
107 warn!(field = ?f, "dropping field which cannot be parsed as unstructured");
108 }
109 }
110 e
111 }
112}