@@ -122,50 +122,32 @@ pub fn vec_to_data_uri(bytes: &[u8]) -> String {
122122 vec_to_data_uri_with_mime ( bytes, mime_type)
123123}
124124
125- /// Detects MIME type based on file signatures (magic bytes).
126- /// Returns the most appropriate MIME type for common file formats.
127125pub fn detect_mime_type ( bytes : & [ u8 ] ) -> & ' static str {
128126 if bytes. is_empty ( ) {
129127 return "application/octet-stream" ;
130128 }
131129
132- // Check for PNG (Portable Network Graphics)
133- if bytes. len ( ) >= 8 && & bytes[ 0 ..8 ] == & [ 0x89 , 0x50 , 0x4E , 0x47 , 0x0D , 0x0A , 0x1A , 0x0A ] {
130+ if bytes. starts_with ( & [ 0x89 , 0x50 , 0x4E , 0x47 , 0x0D , 0x0A , 0x1A , 0x0A ] ) {
134131 return "image/png" ;
135132 }
136-
137- // Check for JPEG (Joint Photographic Experts Group)
138- if bytes. len ( ) >= 2 && & bytes[ 0 ..2 ] == & [ 0xFF , 0xD8 ] {
133+ if bytes. starts_with ( & [ 0xFF , 0xD8 ] ) {
139134 return "image/jpeg" ;
140135 }
141-
142- // Check for GIF (Graphics Interchange Format)
143- if bytes. len ( ) >= 6 {
144- if & bytes[ 0 ..6 ] == & [ 0x47 , 0x49 , 0x46 , 0x38 , 0x37 , 0x61 ] || // GIF87a
145- & bytes[ 0 ..6 ] == & [ 0x47 , 0x49 , 0x46 , 0x38 , 0x39 , 0x61 ] { // GIF89a
146- return "image/gif" ;
147- }
136+ if bytes. starts_with ( & [ 0x47 , 0x49 , 0x46 , 0x38 , 0x37 , 0x61 ] ) ||
137+ bytes. starts_with ( & [ 0x47 , 0x49 , 0x46 , 0x38 , 0x39 , 0x61 ] ) {
138+ return "image/gif" ;
148139 }
149-
150- // Check for BMP (Bitmap)
151- if bytes. len ( ) >= 2 && & bytes[ 0 ..2 ] == & [ 0x42 , 0x4D ] {
140+ if bytes. starts_with ( & [ 0x42 , 0x4D ] ) {
152141 return "image/bmp" ;
153142 }
154-
155- // Check for WebP
156- if bytes. len ( ) >= 12 && & bytes[ 0 ..4 ] == & [ 0x52 , 0x49 , 0x46 , 0x46 ] &&
143+ if bytes. starts_with ( & [ 0x52 , 0x49 , 0x46 , 0x46 ] ) && bytes. len ( ) >= 12 &&
157144 & bytes[ 8 ..12 ] == & [ 0x57 , 0x45 , 0x42 , 0x50 ] {
158145 return "image/webp" ;
159146 }
160-
161- // Check for PDF (Portable Document Format)
162- if bytes. len ( ) >= 4 && & bytes[ 0 ..4 ] == & [ 0x25 , 0x50 , 0x44 , 0x46 ] {
147+ if bytes. starts_with ( & [ 0x25 , 0x50 , 0x44 , 0x46 ] ) {
163148 return "application/pdf" ;
164149 }
165-
166- // Check for ZIP (including DOCX, XLSX, etc.)
167- if bytes. len ( ) >= 4 && & bytes[ 0 ..4 ] == & [ 0x50 , 0x4B , 0x03 , 0x04 ] {
168- // Check for specific ZIP-based formats
150+ if bytes. starts_with ( & [ 0x50 , 0x4B , 0x03 , 0x04 ] ) {
169151 if bytes. len ( ) >= 50 {
170152 let content = String :: from_utf8_lossy ( & bytes[ 30 ..50 ] ) ;
171153 if content. contains ( "word/" ) {
@@ -181,34 +163,19 @@ pub fn detect_mime_type(bytes: &[u8]) -> &'static str {
181163 return "application/zip" ;
182164 }
183165
184- // Check for JSON (simple heuristic)
185- if bytes. len ( ) >= 2 {
186- let start = String :: from_utf8_lossy ( & bytes[ ..bytes. len ( ) . min ( 10 ) ] ) ;
187- let trimmed = start. trim ( ) ;
188- if trimmed. starts_with ( '{' ) || trimmed. starts_with ( '[' ) {
189- return "application/json" ;
190- }
191- }
166+ let start = String :: from_utf8_lossy ( & bytes[ ..bytes. len ( ) . min ( 100 ) ] ) ;
167+ let trimmed = start. trim_start ( ) ;
192168
193- // Check for SVG (Scalable Vector Graphics) - must come before XML
194- if bytes. len ( ) >= 5 {
195- let start = String :: from_utf8_lossy ( & bytes[ ..bytes. len ( ) . min ( 100 ) ] ) ;
196- let trimmed = start. trim_start ( ) ;
197- if trimmed. starts_with ( "<svg" ) {
198- return "image/svg+xml" ;
199- }
169+ if trimmed. starts_with ( "<svg" ) {
170+ return "image/svg+xml" ;
200171 }
201-
202- // Check for XML - must come after SVG to avoid conflicts
203- if bytes. len ( ) >= 5 {
204- let start = String :: from_utf8_lossy ( & bytes[ ..bytes. len ( ) . min ( 20 ) ] ) ;
205- let trimmed = start. trim_start ( ) ;
206- if trimmed. starts_with ( "<?xml" ) || trimmed. starts_with ( '<' ) {
207- return "application/xml" ;
208- }
172+ if trimmed. starts_with ( "<?xml" ) || trimmed. starts_with ( '<' ) {
173+ return "application/xml" ;
174+ }
175+ if trimmed. starts_with ( '{' ) || trimmed. starts_with ( '[' ) {
176+ return "application/json" ;
209177 }
210178
211- // Default fallback
212179 "application/octet-stream"
213180}
214181
0 commit comments