@@ -28,15 +28,15 @@ use infer::Infer;
2828/// ```
2929// NOTE: we cannot statically initialize Strings with values yet, so we keep dedicated static
3030// fields for the static strings.
31- #[ derive( Clone , PartialEq , Eq , Debug ) ]
31+ #[ derive( Clone ) ]
3232pub 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 > ,
4040}
4141
4242impl Mime {
@@ -68,40 +68,87 @@ impl Mime {
6868 /// According to the spec this method should be named `type`, but that's a reserved keyword in
6969 /// Rust so hence prefix with `base` instead.
7070 pub fn basetype ( & self ) -> & str {
71- & self . basetype
71+ if let Some ( basetype) = self . static_basetype {
72+ & basetype
73+ } else {
74+ & self . basetype
75+ }
7276 }
7377
7478 /// Access the Mime's `subtype` value.
7579 pub fn subtype ( & self ) -> & str {
76- & self . subtype
80+ if let Some ( subtype) = self . static_subtype {
81+ & subtype
82+ } else {
83+ & self . subtype
84+ }
7785 }
7886
7987 /// Access the Mime's `essence` value.
8088 pub fn essence ( & self ) -> & str {
81- & self . essence
89+ if let Some ( essence) = self . static_essence {
90+ & essence
91+ } else {
92+ & self . essence
93+ }
8294 }
8395
8496 /// Get a reference to a param.
8597 pub fn param ( & self , name : impl Into < ParamName > ) -> Option < & ParamValue > {
8698 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 ( )
92111 }
93112
94113 /// Remove a param from the set. Returns the `ParamValue` if it was contained within the set.
95114 pub fn remove_param ( & mut self , name : impl Into < ParamName > ) -> Option < ParamValue > {
96115 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 ;
100136 }
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
105152 }
106153}
107154
@@ -111,11 +158,15 @@ impl Display for Mime {
111158 }
112159}
113160
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+ }
119170
120171impl FromStr for Mime {
121172 type Err = crate :: Error ;
@@ -145,7 +196,6 @@ impl ToHeaderValues for Mime {
145196 Ok ( header. to_header_values ( ) . unwrap ( ) )
146197 }
147198}
148-
149199/// A parameter name.
150200#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
151201pub struct ParamName ( Cow < ' static , str > ) ;
@@ -209,3 +259,11 @@ impl PartialEq<str> for ParamValue {
209259 self . 0 == other
210260 }
211261}
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