@@ -28,15 +28,15 @@ use infer::Infer;
28
28
/// ```
29
29
// NOTE: we cannot statically initialize Strings with values yet, so we keep dedicated static
30
30
// fields for the static strings.
31
- #[ derive( Clone , PartialEq , Eq , Debug ) ]
31
+ #[ derive( Clone ) ]
32
32
pub struct Mime {
33
- pub ( crate ) essence : Cow < ' static , str > ,
34
- pub ( crate ) basetype : Cow < ' static , str > ,
35
- pub ( crate ) subtype : Cow < ' static , str > ,
36
- // NOTE(yosh): this is a hack because we can't populate vecs in const yet.
37
- // This enables us to encode media types as utf-8 at compilation.
38
- pub ( crate ) is_utf8 : bool ,
39
- pub ( crate ) params : Vec < ( ParamName , ParamValue ) > ,
33
+ pub ( crate ) essence : String ,
34
+ pub ( crate ) basetype : String ,
35
+ pub ( crate ) subtype : String ,
36
+ pub ( crate ) static_essence : Option < & ' static str > ,
37
+ pub ( crate ) static_basetype : Option < & ' static str > ,
38
+ pub ( crate ) static_subtype : Option < & ' static str > ,
39
+ pub ( crate ) params : Option < ParamKind > ,
40
40
}
41
41
42
42
impl Mime {
@@ -68,40 +68,87 @@ impl Mime {
68
68
/// According to the spec this method should be named `type`, but that's a reserved keyword in
69
69
/// Rust so hence prefix with `base` instead.
70
70
pub fn basetype ( & self ) -> & str {
71
- & self . basetype
71
+ if let Some ( basetype) = self . static_basetype {
72
+ & basetype
73
+ } else {
74
+ & self . basetype
75
+ }
72
76
}
73
77
74
78
/// Access the Mime's `subtype` value.
75
79
pub fn subtype ( & self ) -> & str {
76
- & self . subtype
80
+ if let Some ( subtype) = self . static_subtype {
81
+ & subtype
82
+ } else {
83
+ & self . subtype
84
+ }
77
85
}
78
86
79
87
/// Access the Mime's `essence` value.
80
88
pub fn essence ( & self ) -> & str {
81
- & self . essence
89
+ if let Some ( essence) = self . static_essence {
90
+ & essence
91
+ } else {
92
+ & self . essence
93
+ }
82
94
}
83
95
84
96
/// Get a reference to a param.
85
97
pub fn param ( & self , name : impl Into < ParamName > ) -> Option < & ParamValue > {
86
98
let name: ParamName = name. into ( ) ;
87
- if name. as_str ( ) == "charset" && self . is_utf8 {
88
- return Some ( & ParamValue ( Cow :: Borrowed ( "utf-8" ) ) ) ;
89
- }
90
-
91
- self . params . iter ( ) . find ( |( k, _) | k == & name) . map ( |( _, v) | v)
99
+ self . params
100
+ . as_ref ( )
101
+ . map ( |inner| match inner {
102
+ ParamKind :: Vec ( v) => v
103
+ . iter ( )
104
+ . find_map ( |( k, v) | if k == & name { Some ( v) } else { None } ) ,
105
+ ParamKind :: Utf8 => match name {
106
+ ParamName ( Cow :: Borrowed ( "charset" ) ) => Some ( & ParamValue ( Cow :: Borrowed ( "utf8" ) ) ) ,
107
+ _ => None ,
108
+ } ,
109
+ } )
110
+ . flatten ( )
92
111
}
93
112
94
113
/// Remove a param from the set. Returns the `ParamValue` if it was contained within the set.
95
114
pub fn remove_param ( & mut self , name : impl Into < ParamName > ) -> Option < ParamValue > {
96
115
let name: ParamName = name. into ( ) ;
97
- if name. as_str ( ) == "charset" && self . is_utf8 {
98
- self . is_utf8 = false ;
99
- return Some ( ParamValue ( Cow :: Borrowed ( "utf-8" ) ) ) ;
116
+ let mut unset_params = false ;
117
+ let ret = self
118
+ . params
119
+ . as_mut ( )
120
+ . map ( |inner| match inner {
121
+ ParamKind :: Vec ( v) => match v. iter ( ) . position ( |( k, _) | k == & name) {
122
+ Some ( index) => Some ( v. remove ( index) . 1 ) ,
123
+ None => None ,
124
+ } ,
125
+ ParamKind :: Utf8 => match name {
126
+ ParamName ( Cow :: Borrowed ( "charset" ) ) => {
127
+ unset_params = true ;
128
+ Some ( ParamValue ( Cow :: Borrowed ( "utf8" ) ) )
129
+ }
130
+ _ => None ,
131
+ } ,
132
+ } )
133
+ . flatten ( ) ;
134
+ if unset_params {
135
+ self . params = None ;
100
136
}
101
- self . params
102
- . iter ( )
103
- . position ( |( k, _) | k == & name)
104
- . map ( |pos| self . params . remove ( pos) . 1 )
137
+ ret
138
+ }
139
+ }
140
+
141
+ impl PartialEq < Mime > for Mime {
142
+ fn eq ( & self , other : & Mime ) -> bool {
143
+ let left = match self . static_essence {
144
+ Some ( essence) => essence,
145
+ None => & self . essence ,
146
+ } ;
147
+ let right = match other. static_essence {
148
+ Some ( essence) => essence,
149
+ None => & other. essence ,
150
+ } ;
151
+ left == right
105
152
}
106
153
}
107
154
@@ -111,11 +158,15 @@ impl Display for Mime {
111
158
}
112
159
}
113
160
114
- // impl Debug for Mime {
115
- // fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116
- // Debug::fmt(&self.essence, f)
117
- // }
118
- // }
161
+ impl Debug for Mime {
162
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
163
+ if let Some ( essence) = self . static_essence {
164
+ Debug :: fmt ( essence, f)
165
+ } else {
166
+ Debug :: fmt ( & self . essence , f)
167
+ }
168
+ }
169
+ }
119
170
120
171
impl FromStr for Mime {
121
172
type Err = crate :: Error ;
@@ -145,7 +196,6 @@ impl ToHeaderValues for Mime {
145
196
Ok ( header. to_header_values ( ) . unwrap ( ) )
146
197
}
147
198
}
148
-
149
199
/// A parameter name.
150
200
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
151
201
pub struct ParamName ( Cow < ' static , str > ) ;
@@ -209,3 +259,11 @@ impl PartialEq<str> for ParamValue {
209
259
self . 0 == other
210
260
}
211
261
}
262
+
263
+ /// This is a hack that allows us to mark a trait as utf8 during compilation. We
264
+ /// can remove this once we can construct HashMap during compilation.
265
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
266
+ pub ( crate ) enum ParamKind {
267
+ Utf8 ,
268
+ Vec ( Vec < ( ParamName , ParamValue ) > ) ,
269
+ }
0 commit comments