1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[allow(non_camel_case_types)]
9pub enum FileType {
10 Jpeg,
12 Tiff,
13 Png,
14 Gif,
15 Bmp,
16 WebP,
17 Heif,
18 Avif,
19 Psd,
20 Jp2,
21 J2c,
22 Jxl,
23 Jxr,
24 Flif,
25 Bpg,
26 Exr,
27 Ico,
28 Jps,
29 DjVu,
31 Xcf,
32 Pcx,
33 Pict,
34 Psp,
35 Hdr,
36 Rwz,
37 Btf,
38 Mng,
39 PhotoCd,
40 Cr2,
42 Cr3,
43 Crw,
44 Nef,
45 Arw,
46 Sr2,
47 Srf,
48 Orf,
49 Rw2,
50 Dng,
51 Raf,
52 Pef,
53 Dcr,
54 Mrw,
55 Erf,
56 Fff,
57 Iiq,
58 Rwl,
59 Mef,
60 Srw,
61 X3f,
62 Gpr,
63 Arq,
64 ThreeFR,
65 Crm,
66 Mp4,
68 QuickTime,
69 Avi,
70 Mkv,
71 WebM,
72 Wmv,
73 Asf,
74 Flv,
75 Mxf,
76 Czi,
77 M2ts,
78 Mpeg,
79 ThreeGP,
80 RealMedia,
81 R3d,
82 Dvb,
83 Lrv,
84 Mqv,
85 F4v,
86 Wtv,
87 DvrMs,
88 Mp3,
90 Flac,
91 Ogg,
92 Wav,
93 Aiff,
94 Aac,
95 Opus,
96 Mpc,
97 Ape,
98 WavPack,
99 Ofr,
100 Dsf,
101 Audible,
102 RealAudio,
103 Wma,
104 M4a,
105 Dss,
106 Pdf,
108 PostScript,
109 Doc,
110 Docx,
111 Xls,
112 Xlsx,
113 Ppt,
114 Pptx,
115 Numbers,
116 Pages,
117 Key,
118 InDesign,
119 Rtf,
120 Zip,
122 Rar,
123 SevenZ,
124 Gzip,
125 Xmp,
127 Mie,
128 Exv,
129 Vrd,
130 Dr4,
131 Icc,
132 Html,
133 Exe,
134 Font,
135 Swf,
136 Dicom,
137 Fits,
138 Fit,
139 Mrc,
141 Moi,
142 MacOs,
143 Json,
144 Pcap,
145 Pcapng,
146 Svg,
147 Pgf,
149 Xisf,
150 Torrent,
151 Mobi,
152 SonyPmp,
153 Plist,
155 Aae,
156 KyoceraRaw,
157 Lfp,
159 PortableFloatMap,
161 Fpf,
163 Ods,
165 Odt,
166 Odp,
167 Odg,
168 Odf,
169 Odb,
170 Odi,
171 Odc,
172 Eip,
174 Lif,
176 Txt,
178 Csv,
179 Vcard,
180 Ics,
181 Url,
182 Lnk,
183 Ppm,
184 Dpx,
185 Ram,
186 Miff,
188 Tnef,
189 Wpg,
190 Dv,
191 Itc,
192 Iso,
193 Afm,
194 Pfa,
195 Pfb,
196 Dfont,
197 Xml,
198 Inx,
199 Eps,
200}
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq)]
204pub enum Support {
205 Read,
206 ReadWrite,
207 ReadWriteCreate,
208}
209
210impl FileType {
211 pub fn description(self) -> &'static str {
213 match self {
214 FileType::Jpeg => "JPEG image",
216 FileType::Tiff => "TIFF image",
217 FileType::Png => "PNG image",
218 FileType::Gif => "GIF image",
219 FileType::Bmp => "BMP image",
220 FileType::WebP => "WebP image",
221 FileType::Heif => "HEIF/HEIC image",
222 FileType::Avif => "AVIF image",
223 FileType::Psd => "Adobe Photoshop Document",
224 FileType::Jp2 => "JPEG 2000 image",
225 FileType::J2c => "JPEG 2000 Codestream",
226 FileType::Jxl => "JPEG XL image",
227 FileType::Jxr => "JPEG XR / HD Photo",
228 FileType::Flif => "Free Lossless Image Format",
229 FileType::Bpg => "Better Portable Graphics",
230 FileType::Exr => "OpenEXR image",
231 FileType::Ico => "Windows Icon",
232 FileType::Jps => "JPEG Stereo image",
233 FileType::DjVu => "DjVu document",
235 FileType::Xcf => "GIMP image",
236 FileType::Pcx => "PCX image",
237 FileType::Pict => "Apple PICT",
238 FileType::Psp => "Paint Shop Pro image",
239 FileType::Pgf => "Progressive Graphics File",
240 FileType::Xisf => "PixInsight XISF image",
241 FileType::Torrent => "BitTorrent descriptor",
242 FileType::Mobi => "Mobipocket Book",
243 FileType::SonyPmp => "Sony PMP video",
244 FileType::Plist => "PLIST",
245 FileType::Aae => "AAE",
246 FileType::KyoceraRaw => "Kyocera Contax N RAW",
247 FileType::Lfp => "LFP",
248 FileType::PortableFloatMap => "Portable Float Map",
249 FileType::Hdr => "Radiance HDR",
250 FileType::Rwz => "Rawzor compressed image",
251 FileType::Btf => "BigTIFF image",
252 FileType::Mng => "MNG animation",
253 FileType::PhotoCd => "Kodak Photo CD",
254 FileType::Cr2 => "Canon CR2 RAW",
256 FileType::Cr3 => "Canon CR3 RAW",
257 FileType::Crw => "Canon CRW RAW",
258 FileType::Nef => "Nikon NEF RAW",
259 FileType::Arw => "Sony ARW RAW",
260 FileType::Sr2 => "Sony SR2 RAW",
261 FileType::Srf => "Sony SRF RAW",
262 FileType::Orf => "Olympus ORF RAW",
263 FileType::Rw2 => "Panasonic RW2 RAW",
264 FileType::Dng => "Adobe Digital Negative",
265 FileType::Raf => "Fujifilm RAF RAW",
266 FileType::Pef => "Pentax PEF RAW",
267 FileType::Dcr => "Kodak DCR RAW",
268 FileType::Mrw => "Minolta MRW RAW",
269 FileType::Erf => "Epson ERF RAW",
270 FileType::Fff => "Hasselblad FFF RAW",
271 FileType::Iiq => "Phase One IIQ RAW",
272 FileType::Rwl => "Leica RWL RAW",
273 FileType::Mef => "Mamiya MEF RAW",
274 FileType::Srw => "Samsung SRW RAW",
275 FileType::X3f => "Sigma X3F RAW",
276 FileType::Gpr => "GoPro GPR RAW",
277 FileType::Arq => "Sony ARQ RAW",
278 FileType::ThreeFR => "Hasselblad 3FR RAW",
279 FileType::Crm => "Canon Cinema RAW",
280 FileType::Mp4 => "MP4 video",
282 FileType::QuickTime => "QuickTime video",
283 FileType::Avi => "AVI",
284 FileType::Mkv => "Matroska video",
285 FileType::WebM => "WebM video",
286 FileType::Wmv => "Windows Media Video",
287 FileType::Asf => "Advanced Systems Format",
288 FileType::Flv => "Flash Video",
289 FileType::Mxf => "Material Exchange Format",
290 FileType::Czi => "CZI",
291 FileType::M2ts => "MPEG-2 Transport Stream",
292 FileType::Mpeg => "MPEG video",
293 FileType::ThreeGP => "3GPP multimedia",
294 FileType::RealMedia => "RealMedia",
295 FileType::R3d => "Redcode RAW video",
296 FileType::Dvb => "Digital Video Broadcasting",
297 FileType::Lrv => "GoPro Low-Res Video",
298 FileType::Mqv => "Sony Movie",
299 FileType::F4v => "Adobe Flash Video",
300 FileType::Wtv => "Windows Recorded TV",
301 FileType::DvrMs => "Microsoft DVR",
302 FileType::Mp3 => "MP3 audio",
304 FileType::Flac => "FLAC audio",
305 FileType::Ogg => "Ogg Vorbis audio",
306 FileType::Wav => "WAV audio",
307 FileType::Aiff => "AIFF",
308 FileType::Aac => "AAC audio",
309 FileType::Opus => "Opus audio",
310 FileType::Mpc => "Musepack audio",
311 FileType::Ape => "Monkey's Audio",
312 FileType::WavPack => "WavPack audio",
313 FileType::Ofr => "OptimFROG audio",
314 FileType::Dsf => "DSD Stream File",
315 FileType::Audible => "Audible audiobook",
316 FileType::RealAudio => "RealAudio",
317 FileType::Wma => "Windows Media Audio",
318 FileType::M4a => "MPEG-4 Audio",
319 FileType::Dss => "DSS",
320 FileType::Pdf => "PDF document",
322 FileType::PostScript => "PostScript",
323 FileType::Doc => "Microsoft Word (legacy)",
324 FileType::Docx => "Microsoft Word",
325 FileType::Xls => "Microsoft Excel (legacy)",
326 FileType::Xlsx => "Microsoft Excel",
327 FileType::Ppt => "Microsoft PowerPoint (legacy)",
328 FileType::Pptx => "Microsoft PowerPoint",
329 FileType::Numbers => "Apple Numbers",
330 FileType::Pages => "Apple Pages",
331 FileType::Key => "Apple Keynote",
332 FileType::InDesign => "Adobe InDesign",
333 FileType::Rtf => "Rich Text Format",
334 FileType::Zip => "ZIP archive",
336 FileType::Rar => "RAR archive",
337 FileType::SevenZ => "7-Zip archive",
338 FileType::Gzip => "GZIP",
339 FileType::Xmp => "XMP sidecar",
341 FileType::Mie => "MIE metadata",
342 FileType::Exv => "Exiv2 metadata",
343 FileType::Vrd => "VRD",
344 FileType::Dr4 => "DR4",
345 FileType::Icc => "ICC color profile",
346 FileType::Html => "HTML document",
347 FileType::Exe => "Windows executable",
348 FileType::Font => "Font file",
349 FileType::Swf => "Shockwave Flash",
350 FileType::Dicom => "DICOM medical image",
351 FileType::Fits => "FITS astronomical image",
352 FileType::Fit => "Garmin Flexible and Interoperable Data Transfer",
353 FileType::Mrc => "MRC image",
354 FileType::Moi => "MOI",
355 FileType::MacOs => "MacOS",
356 FileType::Json => "JSON",
357 FileType::Pcap => "PCAP",
358 FileType::Pcapng => "PCAPNG",
359 FileType::Svg => "SVG",
360 FileType::Fpf => "FPF",
361 FileType::Ods => "ODS",
362 FileType::Odt => "ODT",
363 FileType::Odp => "ODP",
364 FileType::Odg => "ODG",
365 FileType::Odf => "ODF",
366 FileType::Odb => "ODB",
367 FileType::Odi => "ODI",
368 FileType::Odc => "ODC",
369 FileType::Eip => "EIP",
370 FileType::Lif => "Leica Image Format",
371 FileType::Txt => "Text",
372 FileType::Csv => "Comma-Separated Values",
373 FileType::Vcard => "vCard",
374 FileType::Ics => "iCalendar",
375 FileType::Url => "Windows URL Shortcut",
376 FileType::Lnk => "Windows Shortcut",
377 FileType::Ppm => "Portable Pixel Map",
378 FileType::Dpx => "Digital Picture Exchange",
379 FileType::Ram => "Real Audio Metadata",
380 FileType::Miff => "Magick Image File Format",
381 FileType::Tnef => "Transport Neutral Encapsulation Format",
382 FileType::Wpg => "WordPerfect Graphics",
383 FileType::Dv => "Digital Video",
384 FileType::Itc => "iTunes Cover Flow",
385 FileType::Iso => "ISO 9660 disk image",
386 FileType::Afm => "Adobe Font Metrics",
387 FileType::Pfa => "PostScript Font ASCII",
388 FileType::Pfb => "PostScript Font Binary",
389 FileType::Dfont => "Macintosh Font",
390 FileType::Xml => "Extensible Markup Language",
391 FileType::Inx => "Adobe InDesign Interchange",
392 FileType::Eps => "Encapsulated PostScript",
393 }
394 }
395
396 pub fn code(self) -> &'static str {
399 match self {
400 FileType::Jpeg => "JPEG",
401 FileType::Tiff => "TIFF",
402 FileType::Png => "PNG",
403 FileType::Gif => "GIF",
404 FileType::Bmp => "BMP",
405 FileType::WebP => "WEBP",
406 FileType::Heif => "HEIF",
407 FileType::Avif => "AVIF",
408 FileType::Psd => "PSD",
409 FileType::Jp2 => "JP2",
410 FileType::J2c => "J2C",
411 FileType::Jxl => "JXL",
412 FileType::Jxr => "JXR",
413 FileType::Flif => "FLIF",
414 FileType::Bpg => "BPG",
415 FileType::Exr => "EXR",
416 FileType::Ico => "ICO",
417 FileType::Jps => "JPS",
418 FileType::DjVu => "DJVU",
419 FileType::Xcf => "XCF",
420 FileType::Pcx => "PCX",
421 FileType::Pict => "PICT",
422 FileType::Psp => "PSP",
423 FileType::Pgf => "PGF",
424 FileType::Xisf => "XISF",
425 FileType::Torrent => "Torrent",
426 FileType::Mobi => "MOBI",
427 FileType::SonyPmp => "PMP",
428 FileType::Plist => "PLIST",
429 FileType::Aae => "AAE",
430 FileType::KyoceraRaw => "RAW",
431 FileType::Lfp => "LFP",
432 FileType::PortableFloatMap => "PFM",
433 FileType::Hdr => "HDR",
434 FileType::Rwz => "RWZ",
435 FileType::Btf => "BTF",
436 FileType::Mng => "MNG",
437 FileType::PhotoCd => "PCD",
438 FileType::Cr2 => "CR2",
439 FileType::Cr3 => "CR3",
440 FileType::Crw => "CRW",
441 FileType::Nef => "NEF",
442 FileType::Arw => "ARW",
443 FileType::Sr2 => "SR2",
444 FileType::Srf => "SRF",
445 FileType::Orf => "ORF",
446 FileType::Rw2 => "RW2",
447 FileType::Dng => "DNG",
448 FileType::Raf => "RAF",
449 FileType::Pef => "PEF",
450 FileType::Dcr => "DCR",
451 FileType::Mrw => "MRW",
452 FileType::Erf => "ERF",
453 FileType::Fff => "FFF",
454 FileType::Iiq => "IIQ",
455 FileType::Rwl => "RWL",
456 FileType::Mef => "MEF",
457 FileType::Srw => "SRW",
458 FileType::X3f => "X3F",
459 FileType::Gpr => "GPR",
460 FileType::Arq => "ARQ",
461 FileType::ThreeFR => "3FR",
462 FileType::Crm => "CRM",
463 FileType::Mp4 => "MP4",
464 FileType::QuickTime => "MOV",
465 FileType::Avi => "AVI",
466 FileType::Mkv => "MKV",
467 FileType::WebM => "WEBM",
468 FileType::Wmv => "WMV",
469 FileType::Asf => "ASF",
470 FileType::Flv => "FLV",
471 FileType::Mxf => "MXF",
472 FileType::Czi => "CZI",
473 FileType::M2ts => "M2TS",
474 FileType::Mpeg => "MPEG",
475 FileType::ThreeGP => "3GP",
476 FileType::RealMedia => "RM",
477 FileType::R3d => "R3D",
478 FileType::Dvb => "DVB",
479 FileType::Lrv => "LRV",
480 FileType::Mqv => "MQV",
481 FileType::F4v => "F4V",
482 FileType::Wtv => "WTV",
483 FileType::DvrMs => "DVR-MS",
484 FileType::Mp3 => "MP3",
485 FileType::Flac => "FLAC",
486 FileType::Ogg => "OGG",
487 FileType::Wav => "WAV",
488 FileType::Aiff => "AIFF",
489 FileType::Aac => "AAC",
490 FileType::Opus => "OPUS",
491 FileType::Mpc => "MPC",
492 FileType::Ape => "APE",
493 FileType::WavPack => "WV",
494 FileType::Ofr => "OFR",
495 FileType::Dsf => "DSF",
496 FileType::Audible => "AA",
497 FileType::RealAudio => "RA",
498 FileType::Wma => "WMA",
499 FileType::M4a => "M4A",
500 FileType::Dss => "DSS",
501 FileType::Pdf => "PDF",
502 FileType::PostScript => "PS",
503 FileType::Doc => "DOC",
504 FileType::Docx => "DOCX",
505 FileType::Xls => "XLS",
506 FileType::Xlsx => "XLSX",
507 FileType::Ppt => "PPT",
508 FileType::Pptx => "PPTX",
509 FileType::Numbers => "NUMBERS",
510 FileType::Pages => "PAGES",
511 FileType::Key => "KEY",
512 FileType::InDesign => "INDD",
513 FileType::Rtf => "RTF",
514 FileType::Zip => "ZIP",
515 FileType::Rar => "RAR",
516 FileType::SevenZ => "7Z",
517 FileType::Gzip => "GZIP",
518 FileType::Xmp => "XMP",
519 FileType::Mie => "MIE",
520 FileType::Exv => "EXV",
521 FileType::Vrd => "VRD",
522 FileType::Dr4 => "DR4",
523 FileType::Icc => "ICC",
524 FileType::Html => "HTML",
525 FileType::Exe => "EXE",
526 FileType::Font => "TTF",
527 FileType::Swf => "SWF",
528 FileType::Dicom => "DICOM",
529 FileType::Fits => "FITS",
530 FileType::Fit => "FIT",
531 FileType::Mrc => "MRC",
532 FileType::Moi => "MOI",
533 FileType::MacOs => "MacOS",
534 FileType::Json => "JSON",
535 FileType::Pcap => "PCAP",
536 FileType::Pcapng => "PCAPNG",
537 FileType::Svg => "SVG",
538 FileType::Fpf => "FPF",
539 FileType::Ods => "ODS",
540 FileType::Odt => "ODT",
541 FileType::Odp => "ODP",
542 FileType::Odg => "ODG",
543 FileType::Odf => "ODF",
544 FileType::Odb => "ODB",
545 FileType::Odi => "ODI",
546 FileType::Odc => "ODC",
547 FileType::Eip => "EIP",
548 FileType::Lif => "LIF",
549 FileType::Txt => "TXT",
550 FileType::Csv => "CSV",
551 FileType::Vcard => "VCard",
552 FileType::Ics => "ICS",
553 FileType::Url => "URL",
554 FileType::Lnk => "LNK",
555 FileType::Ppm => "PPM",
556 FileType::Dpx => "DPX",
557 FileType::Ram => "RAM",
558 FileType::Miff => "MIFF",
559 FileType::Tnef => "TNEF",
560 FileType::Wpg => "WPG",
561 FileType::Dv => "DV",
562 FileType::Itc => "ITC",
563 FileType::Iso => "ISO",
564 FileType::Afm => "AFM",
565 FileType::Pfa => "PFA",
566 FileType::Pfb => "PFB",
567 FileType::Dfont => "DFONT",
568 FileType::Xml => "XML",
569 FileType::Inx => "INX",
570 FileType::Eps => "EPS",
571 }
572 }
573
574 pub fn mime_type(self) -> &'static str {
576 match self {
577 FileType::Jpeg => "image/jpeg",
578 FileType::Tiff => "image/tiff",
579 FileType::Btf => "image/x-tiff-big",
580 FileType::Png => "image/png",
581 FileType::Gif => "image/gif",
582 FileType::Bmp => "image/bmp",
583 FileType::WebP => "image/webp",
584 FileType::Heif => "image/heif",
585 FileType::Avif => "image/avif",
586 FileType::Psd => "application/vnd.adobe.photoshop",
587 FileType::Jp2 => "image/jp2",
588 FileType::J2c => "image/x-j2c",
589 FileType::Jxl => "image/jxl",
590 FileType::Jxr => "image/jxr",
591 FileType::Flif => "image/flif",
592 FileType::Bpg => "image/bpg",
593 FileType::Exr => "image/x-exr",
594 FileType::Ico => "image/x-icon",
595 FileType::Jps => "image/x-jps",
596 FileType::DjVu => "image/vnd.djvu",
597 FileType::Xcf => "image/x-xcf",
598 FileType::Pcx => "image/pcx",
599 FileType::Pict => "image/pict",
600 FileType::Psp => "image/x-paintshoppro",
601 FileType::Hdr => "image/vnd.radiance",
602 FileType::Rwz => "image/x-rawzor",
603 FileType::Mng => "video/x-mng",
604 FileType::PhotoCd => "image/x-photo-cd",
605 FileType::Cr2 => "image/x-canon-cr2",
607 FileType::Cr3 | FileType::Crm => "image/x-canon-cr3",
608 FileType::Crw => "image/x-canon-crw",
609 FileType::Nef => "image/x-nikon-nef",
610 FileType::Arw | FileType::Arq => "image/x-sony-arw",
611 FileType::Sr2 => "image/x-sony-sr2",
612 FileType::Srf => "image/x-sony-srf",
613 FileType::Orf => "image/x-olympus-orf",
614 FileType::Rw2 => "image/x-panasonic-rw2",
615 FileType::Dng | FileType::Gpr => "image/x-adobe-dng",
616 FileType::Raf => "image/x-fujifilm-raf",
617 FileType::Pef => "image/x-pentax-pef",
618 FileType::Dcr => "image/x-kodak-dcr",
619 FileType::Mrw => "image/x-minolta-mrw",
620 FileType::Erf => "image/x-epson-erf",
621 FileType::Fff | FileType::ThreeFR => "image/x-hasselblad-fff",
622 FileType::Iiq => "image/x-raw",
623 FileType::Rwl => "image/x-leica-rwl",
624 FileType::Mef => "image/x-mamiya-mef",
625 FileType::Srw => "image/x-samsung-srw",
626 FileType::X3f => "image/x-sigma-x3f",
627 FileType::Mp4 | FileType::F4v => "video/mp4",
629 FileType::QuickTime | FileType::Mqv => "video/quicktime",
630 FileType::Avi => "video/x-msvideo",
631 FileType::Mkv => "video/x-matroska",
632 FileType::WebM => "video/webm",
633 FileType::Wmv => "video/x-ms-wmv",
634 FileType::Asf => "video/x-ms-asf",
635 FileType::Flv => "video/x-flv",
636 FileType::Mxf => "application/mxf",
637 FileType::Czi => "image/x-zeiss-czi",
638 FileType::M2ts => "video/m2ts",
639 FileType::Mpeg => "video/mpeg",
640 FileType::ThreeGP => "video/3gpp",
641 FileType::RealMedia => "application/vnd.rn-realmedia",
642 FileType::R3d => "video/x-red-r3d",
643 FileType::Dvb => "video/dvb",
644 FileType::Lrv => "video/mp4",
645 FileType::Wtv => "video/x-ms-wtv",
646 FileType::DvrMs => "video/x-ms-dvr",
647 FileType::Mp3 => "audio/mpeg",
649 FileType::Flac => "audio/flac",
650 FileType::Ogg | FileType::Opus => "audio/ogg",
651 FileType::Wav => "audio/x-wav",
652 FileType::Aiff => "audio/x-aiff",
653 FileType::Aac => "audio/aac",
654 FileType::Mpc => "audio/x-musepack",
655 FileType::Ape => "audio/x-monkeys-audio",
656 FileType::WavPack => "audio/x-wavpack",
657 FileType::Ofr => "audio/x-ofr",
658 FileType::Dsf => "audio/dsf",
659 FileType::Audible => "audio/audible",
660 FileType::RealAudio => "audio/x-pn-realaudio",
661 FileType::Wma => "audio/x-ms-wma",
662 FileType::M4a => "audio/mp4",
663 FileType::Dss => "audio/x-dss",
664 FileType::Pdf => "application/pdf",
666 FileType::PostScript => "application/postscript",
667 FileType::Doc => "application/msword",
668 FileType::Docx => {
669 "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
670 }
671 FileType::Xls => "application/vnd.ms-excel",
672 FileType::Xlsx => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
673 FileType::Ppt => "application/vnd.ms-powerpoint",
674 FileType::Pptx => {
675 "application/vnd.openxmlformats-officedocument.presentationml.presentation"
676 }
677 FileType::Numbers => "application/x-iwork-numbers-sffnumbers",
678 FileType::Pages => "application/x-iwork-pages-sffpages",
679 FileType::Key => "application/x-iwork-keynote-sffkey",
680 FileType::InDesign => "application/x-indesign",
681 FileType::Rtf => "text/rtf",
682 FileType::Zip => "application/zip",
684 FileType::Rar => "application/x-rar-compressed",
685 FileType::SevenZ => "application/x-7z-compressed",
686 FileType::Gzip => "application/x-gzip",
687 FileType::Xmp => "application/rdf+xml",
689 FileType::Mie => "application/x-mie",
690 FileType::Exv => "application/x-exv",
691 FileType::Vrd => "application/octet-stream",
692 FileType::Dr4 => "application/octet-stream",
693 FileType::Icc => "application/vnd.iccprofile",
694 FileType::Html => "text/html",
695 FileType::Exe => "application/x-dosexec",
696 FileType::Font => "application/font-ttf",
697 FileType::Swf => "application/x-shockwave-flash",
698 FileType::Dicom => "application/dicom",
699 FileType::Fits => "image/fits",
700 FileType::Fit => "application/fit",
701 FileType::Mrc => "image/x-mrc",
702 FileType::Moi => "application/octet-stream",
703 FileType::MacOs => "application/unknown",
704 FileType::Json => "application/json",
705 FileType::Pcap => "application/vnd.tcpdump.pcap",
706 FileType::Pcapng => "application/vnd.tcpdump.pcap",
707 FileType::Svg => "image/svg+xml",
708 FileType::Pgf => "image/pgf",
709 FileType::Xisf => "image/x-xisf",
710 FileType::Torrent => "application/x-bittorrent",
711 FileType::Mobi => "application/x-mobipocket-ebook",
712 FileType::SonyPmp => "image/x-sony-pmp",
713 FileType::Plist => "application/x-plist",
714 FileType::Aae => "application/vnd.apple.photos",
715 FileType::KyoceraRaw => "image/x-raw",
716 FileType::Lfp => "image/x-lytro-lfp",
717 FileType::PortableFloatMap => "image/x-pfm",
718 FileType::Fpf => "image/x-flir-fpf",
719 FileType::Ods => "application/vnd.oasis.opendocument.spreadsheet",
720 FileType::Odt => "application/vnd.oasis.opendocument.text",
721 FileType::Odp => "application/vnd.oasis.opendocument.presentation",
722 FileType::Odg => "application/vnd.oasis.opendocument.graphics",
723 FileType::Odf => "application/vnd.oasis.opendocument.formula",
724 FileType::Odb => "application/vnd.oasis.opendocument.database",
725 FileType::Odi => "application/vnd.oasis.opendocument.image",
726 FileType::Odc => "application/vnd.oasis.opendocument.chart",
727 FileType::Eip => "application/x-captureone",
728 FileType::Lif => "image/x-leica-lif",
729 FileType::Txt => "text/plain",
730 FileType::Csv => "text/csv",
731 FileType::Vcard => "text/vcard",
732 FileType::Ics => "text/calendar",
733 FileType::Url => "application/x-mswinurl",
734 FileType::Lnk => "application/octet-stream",
735 FileType::Ppm => "image/x-portable-pixmap",
736 FileType::Dpx => "image/x-dpx",
737 FileType::Ram => "audio/x-pn-realaudio",
738 FileType::Miff => "application/x-magick-image",
739 FileType::Tnef => "application/vnd.ms-tnef",
740 FileType::Wpg => "image/x-wpg",
741 FileType::Dv => "video/x-dv",
742 FileType::Itc => "application/itunes",
743 FileType::Iso => "application/x-iso9660-image",
744 FileType::Afm => "application/x-font-afm",
745 FileType::Pfa => "application/x-font-type1",
746 FileType::Pfb => "application/x-font-type1",
747 FileType::Dfont => "application/x-dfont",
748 FileType::Xml => "application/xml",
749 FileType::Inx => "application/x-indesign-interchange",
750 FileType::Eps => "application/postscript",
751 }
752 }
753
754 pub fn extensions(self) -> &'static [&'static str] {
756 match self {
757 FileType::Jpeg => &["jpg", "jpeg", "jpe", "jif", "jfif"],
758 FileType::Tiff => &["tif", "tiff"],
759 FileType::Png => &["png"],
760 FileType::Gif => &["gif"],
761 FileType::Bmp => &["bmp", "dib"],
762 FileType::WebP => &["webp"],
763 FileType::Heif => &["heif", "heic", "hif"],
764 FileType::Avif => &["avif"],
765 FileType::Psd => &["psd", "psb", "psdt"],
766 FileType::Jp2 => &["jp2", "jpf", "jpm", "jpx", "jph"],
767 FileType::J2c => &["j2c", "j2k", "jpc"],
768 FileType::Jxl => &["jxl"],
769 FileType::Jxr => &["jxr", "hdp", "wdp"],
770 FileType::Flif => &["flif"],
771 FileType::Bpg => &["bpg"],
772 FileType::Exr => &["exr"],
773 FileType::Ico => &["ico", "cur"],
774 FileType::Jps => &["jps"],
775 FileType::DjVu => &["djvu", "djv"],
776 FileType::Xcf => &["xcf"],
777 FileType::Pcx => &["pcx"],
778 FileType::Pict => &["pict", "pct"],
779 FileType::Psp => &["psp", "pspimage"],
780 FileType::Hdr => &["hdr"],
781 FileType::Rwz => &["rwz"],
782 FileType::Btf => &["btf"],
783 FileType::Mng => &["mng", "jng"],
784 FileType::PhotoCd => &["pcd"],
785 FileType::Cr2 => &["cr2"],
787 FileType::Cr3 => &["cr3"],
788 FileType::Crw => &["crw", "ciff"],
789 FileType::Nef => &["nef", "nrw"],
790 FileType::Arw => &["arw"],
791 FileType::Sr2 => &["sr2"],
792 FileType::Srf => &["srf"],
793 FileType::Orf => &["orf", "ori"],
794 FileType::Rw2 => &["rw2"],
795 FileType::Dng => &["dng"],
796 FileType::Raf => &["raf"],
797 FileType::Pef => &["pef"],
798 FileType::Dcr => &["dcr"],
799 FileType::Mrw => &["mrw"],
800 FileType::Erf => &["erf"],
801 FileType::Fff => &["fff"],
802 FileType::Iiq => &["iiq"],
803 FileType::Rwl => &["rwl"],
804 FileType::Mef => &["mef"],
805 FileType::Srw => &["srw"],
806 FileType::X3f => &["x3f"],
807 FileType::Gpr => &["gpr"],
808 FileType::Arq => &["arq"],
809 FileType::ThreeFR => &["3fr"],
810 FileType::Crm => &["crm"],
811 FileType::Mp4 => &["mp4", "m4v"],
813 FileType::QuickTime => &["mov", "qt"],
814 FileType::Avi => &["avi"],
815 FileType::Mkv => &["mkv", "mks"],
816 FileType::WebM => &["webm"],
817 FileType::Wmv => &["wmv"],
818 FileType::Asf => &["asf"],
819 FileType::Flv => &["flv"],
820 FileType::Mxf => &["mxf"],
821 FileType::Czi => &["czi"],
822 FileType::M2ts => &["mts", "m2ts", "m2t", "ts"],
823 FileType::Mpeg => &["mpg", "mpeg", "m2v", "mpv"],
824 FileType::ThreeGP => &["3gp", "3gpp", "3g2", "3gp2"],
825 FileType::RealMedia => &["rm", "rv", "rmvb"],
826 FileType::R3d => &["r3d"],
827 FileType::Dvb => &["dvb"],
828 FileType::Lrv => &["lrv", "lrf"],
829 FileType::Mqv => &["mqv"],
830 FileType::F4v => &["f4v", "f4a", "f4b", "f4p"],
831 FileType::Wtv => &["wtv"],
832 FileType::DvrMs => &["dvr-ms"],
833 FileType::Mp3 => &["mp3"],
835 FileType::Flac => &["flac"],
836 FileType::Ogg => &["ogg", "oga", "ogv"],
837 FileType::Wav => &["wav"],
838 FileType::Aiff => &["aiff", "aif", "aifc"],
839 FileType::Aac => &["aac"],
840 FileType::Opus => &["opus"],
841 FileType::Mpc => &["mpc"],
842 FileType::Ape => &["ape"],
843 FileType::WavPack => &["wv", "wvp"],
844 FileType::Ofr => &["ofr"],
845 FileType::Dsf => &["dsf"],
846 FileType::Audible => &["aa", "aax"],
847 FileType::RealAudio => &["ra"],
848 FileType::Wma => &["wma"],
849 FileType::M4a => &["m4a", "m4b", "m4p"],
850 FileType::Dss => &["dss"],
851 FileType::Pdf => &["pdf"],
853 FileType::PostScript => &["ps", "eps", "epsf"],
854 FileType::Doc => &["doc", "dot"],
855 FileType::Docx => &["docx", "docm"],
856 FileType::Xls => &["xls", "xlt"],
857 FileType::Xlsx => &["xlsx", "xlsm", "xlsb"],
858 FileType::Ppt => &["ppt", "pps", "pot"],
859 FileType::Pptx => &["pptx", "pptm"],
860 FileType::Numbers => &["numbers", "nmbtemplate"],
861 FileType::Pages => &["pages"],
862 FileType::Key => &["key", "kth"],
863 FileType::InDesign => &["indd", "ind", "indt"],
864 FileType::Rtf => &["rtf"],
865 FileType::Zip => &["zip"],
867 FileType::Rar => &["rar"],
868 FileType::SevenZ => &["7z"],
869 FileType::Gzip => &["gz", "gzip"],
870 FileType::Xmp => &["xmp"],
872 FileType::Mie => &["mie"],
873 FileType::Exv => &["exv"],
874 FileType::Vrd => &["vrd"],
875 FileType::Dr4 => &["dr4"],
876 FileType::Icc => &["icc", "icm"],
877 FileType::Html => &["html", "htm", "xhtml", "svg"],
878 FileType::Exe => &["exe", "dll", "elf", "so", "dylib", "a", "macho", "o"],
879 FileType::Font => &["ttf", "otf", "woff", "woff2", "ttc"],
880 FileType::Swf => &["swf"],
881 FileType::Dicom => &["dcm"],
882 FileType::Fits => &["fits", "fts"],
883 FileType::Fit => &["fit"],
884 FileType::Mrc => &["mrc"],
885 FileType::Moi => &["moi"],
886 FileType::MacOs => &["macos"],
887 FileType::Json => &["json"],
888 FileType::Pcap => &["pcap", "cap"],
889 FileType::Pcapng => &["pcapng", "ntar"],
890 FileType::Svg => &["svg"],
891 FileType::Pgf => &["pgf"],
892 FileType::Xisf => &["xisf"],
893 FileType::Torrent => &["torrent"],
894 FileType::Mobi => &["mobi", "azw", "azw3"],
895 FileType::SonyPmp => &["pmp"],
896 FileType::Plist => &["plist"],
897 FileType::Aae => &["aae"],
898 FileType::KyoceraRaw => &["raw"],
899 FileType::PortableFloatMap => &["pfm"],
900 FileType::Fpf => &["fpf"],
901 FileType::Ods => &["ods"],
902 FileType::Odt => &["odt"],
903 FileType::Odp => &["odp"],
904 FileType::Odg => &["odg"],
905 FileType::Odf => &["odf"],
906 FileType::Odb => &["odb"],
907 FileType::Odi => &["odi"],
908 FileType::Odc => &["odc"],
909 FileType::Lfp => &["lfp", "lfr"],
910 FileType::Eip => &["eip"],
911 FileType::Lif => &["lif"],
912 FileType::Txt => &["txt", "log", "igc"],
913 FileType::Csv => &["csv"],
914 FileType::Vcard => &["vcf", "vcard"],
915 FileType::Ics => &["ics"],
916 FileType::Url => &["url"],
917 FileType::Lnk => &["lnk"],
918 FileType::Ppm => &["ppm"],
919 FileType::Dpx => &["dpx"],
920 FileType::Ram => &["ram"],
921 FileType::Miff => &["miff", "mif"],
922 FileType::Tnef => &["tnef"],
923 FileType::Wpg => &["wpg"],
924 FileType::Dv => &["dv"],
925 FileType::Itc => &["itc"],
926 FileType::Iso => &["iso"],
927 FileType::Afm => &["afm", "acfm", "amfm"],
928 FileType::Pfa => &["pfa"],
929 FileType::Pfb => &["pfb"],
930 FileType::Dfont => &["dfont"],
931 FileType::Xml => &["xml"],
932 FileType::Inx => &["inx"],
933 FileType::Eps => &["eps", "epsf", "eps3", "epsi", "ept"],
934 }
935 }
936
937 pub fn support(self) -> Support {
939 match self {
940 FileType::Xmp | FileType::Mie | FileType::Exv => Support::ReadWriteCreate,
942 FileType::Jpeg
944 | FileType::Tiff
945 | FileType::Png
946 | FileType::Gif
947 | FileType::WebP
948 | FileType::Heif
949 | FileType::Avif
950 | FileType::Psd
951 | FileType::Jp2
952 | FileType::Jxl
953 | FileType::Jxr
954 | FileType::Flif
955 | FileType::Cr2
956 | FileType::Cr3
957 | FileType::Crw
958 | FileType::Nef
959 | FileType::Arw
960 | FileType::Arq
961 | FileType::Sr2
962 | FileType::Orf
963 | FileType::Rw2
964 | FileType::Dng
965 | FileType::Raf
966 | FileType::Pef
967 | FileType::Erf
968 | FileType::Fff
969 | FileType::Iiq
970 | FileType::Rwl
971 | FileType::Mef
972 | FileType::Srw
973 | FileType::X3f
974 | FileType::Gpr
975 | FileType::Crm
976 | FileType::Mp4
977 | FileType::QuickTime
978 | FileType::ThreeGP
979 | FileType::Dvb
980 | FileType::Lrv
981 | FileType::Mqv
982 | FileType::F4v
983 | FileType::Pdf
984 | FileType::PostScript
985 | FileType::InDesign
986 | FileType::Vrd
987 | FileType::Dr4
988 | FileType::Audible => Support::ReadWrite,
989 _ => Support::Read,
991 }
992 }
993
994 pub fn all() -> &'static [FileType] {
996 ALL_FILE_TYPES
997 }
998}
999
1000static ALL_FILE_TYPES: &[FileType] = &[
1001 FileType::Jpeg,
1003 FileType::Tiff,
1004 FileType::Png,
1005 FileType::Gif,
1006 FileType::Bmp,
1007 FileType::WebP,
1008 FileType::Heif,
1009 FileType::Avif,
1010 FileType::Psd,
1011 FileType::Jp2,
1012 FileType::J2c,
1013 FileType::Jxl,
1014 FileType::Jxr,
1015 FileType::Flif,
1016 FileType::Bpg,
1017 FileType::Exr,
1018 FileType::Ico,
1019 FileType::Jps,
1020 FileType::DjVu,
1022 FileType::Xcf,
1023 FileType::Pcx,
1024 FileType::Pict,
1025 FileType::Psp,
1026 FileType::Hdr,
1027 FileType::Rwz,
1028 FileType::Btf,
1029 FileType::Mng,
1030 FileType::PhotoCd,
1031 FileType::Lif,
1032 FileType::Txt,
1033 FileType::Csv,
1034 FileType::Vcard,
1035 FileType::Ics,
1036 FileType::Url,
1037 FileType::Lnk,
1038 FileType::Ppm,
1039 FileType::Dpx,
1040 FileType::Ram,
1041 FileType::Miff,
1042 FileType::Tnef,
1043 FileType::Wpg,
1044 FileType::Dv,
1045 FileType::Itc,
1046 FileType::Iso,
1047 FileType::Afm,
1048 FileType::Pfa,
1049 FileType::Pfb,
1050 FileType::Dfont,
1051 FileType::Xml,
1052 FileType::Inx,
1053 FileType::Eps,
1054 FileType::Cr2,
1056 FileType::Cr3,
1057 FileType::Crw,
1058 FileType::Nef,
1059 FileType::Arw,
1060 FileType::Sr2,
1061 FileType::Srf,
1062 FileType::Orf,
1063 FileType::Rw2,
1064 FileType::Dng,
1065 FileType::Raf,
1066 FileType::Pef,
1067 FileType::Dcr,
1068 FileType::Mrw,
1069 FileType::Erf,
1070 FileType::Fff,
1071 FileType::Iiq,
1072 FileType::Rwl,
1073 FileType::Mef,
1074 FileType::Srw,
1075 FileType::X3f,
1076 FileType::Gpr,
1077 FileType::Arq,
1078 FileType::ThreeFR,
1079 FileType::Crm,
1080 FileType::Mp4,
1082 FileType::QuickTime,
1083 FileType::Avi,
1084 FileType::Mkv,
1085 FileType::WebM,
1086 FileType::Wmv,
1087 FileType::Asf,
1088 FileType::Flv,
1089 FileType::Mxf,
1090 FileType::M2ts,
1091 FileType::Mpeg,
1092 FileType::ThreeGP,
1093 FileType::RealMedia,
1094 FileType::R3d,
1095 FileType::Dvb,
1096 FileType::Lrv,
1097 FileType::Mqv,
1098 FileType::F4v,
1099 FileType::Wtv,
1100 FileType::DvrMs,
1101 FileType::Mp3,
1103 FileType::Flac,
1104 FileType::Ogg,
1105 FileType::Wav,
1106 FileType::Aiff,
1107 FileType::Aac,
1108 FileType::Opus,
1109 FileType::Mpc,
1110 FileType::Ape,
1111 FileType::WavPack,
1112 FileType::Ofr,
1113 FileType::Dsf,
1114 FileType::Audible,
1115 FileType::RealAudio,
1116 FileType::Wma,
1117 FileType::M4a,
1118 FileType::Dss,
1119 FileType::Pdf,
1121 FileType::PostScript,
1122 FileType::Doc,
1123 FileType::Docx,
1124 FileType::Xls,
1125 FileType::Xlsx,
1126 FileType::Ppt,
1127 FileType::Pptx,
1128 FileType::Numbers,
1129 FileType::Pages,
1130 FileType::Key,
1131 FileType::InDesign,
1132 FileType::Rtf,
1133 FileType::Zip,
1135 FileType::Rar,
1136 FileType::SevenZ,
1137 FileType::Gzip,
1138 FileType::Xmp,
1140 FileType::Mie,
1141 FileType::Exv,
1142 FileType::Vrd,
1143 FileType::Dr4,
1144 FileType::Icc,
1145 FileType::Html,
1146 FileType::Exe,
1147 FileType::Font,
1148 FileType::Swf,
1149 FileType::Dicom,
1150 FileType::Fits,
1151 FileType::Fit,
1152 FileType::Mrc,
1153 FileType::Moi,
1154 FileType::MacOs,
1155 FileType::Json,
1156 FileType::Pcap,
1157 FileType::Pcapng,
1158 FileType::Svg,
1159 FileType::Pgf,
1160 FileType::Xisf,
1161 FileType::Torrent,
1162 FileType::Mobi,
1163 FileType::SonyPmp,
1164 FileType::Plist,
1165 FileType::Aae,
1166 FileType::KyoceraRaw,
1167 FileType::PortableFloatMap,
1168 FileType::Fpf,
1169 FileType::Lfp,
1170 FileType::Ods,
1172 FileType::Odt,
1173 FileType::Odp,
1174 FileType::Odg,
1175 FileType::Odf,
1176 FileType::Odb,
1177 FileType::Odi,
1178 FileType::Odc,
1179 FileType::Eip,
1181];
1182
1183pub fn detect_from_magic(header: &[u8]) -> Option<FileType> {
1185 if header.len() < 4 {
1186 return None;
1187 }
1188
1189 if header.starts_with(&[0xFF, 0xD8, 0xFF]) {
1193 return Some(FileType::Jpeg);
1194 }
1195
1196 if header.starts_with(&[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) {
1198 return Some(FileType::Png);
1199 }
1200
1201 if header.starts_with(&[0x89, 0x4C, 0x46, 0x50, 0x0D, 0x0A, 0x1A, 0x0A]) {
1203 return Some(FileType::Lfp);
1204 }
1205
1206 if header.starts_with(b"GIF8") && header.len() >= 6 && (header[4] == b'7' || header[4] == b'9')
1208 {
1209 return Some(FileType::Gif);
1210 }
1211
1212 if header.len() >= 8
1214 && header.starts_with(b"IIII")
1215 && (header[4] == 0x04 || header[4] == 0x05)
1216 && header[5] == 0x00
1217 && header[6] == 0x04
1218 && header[7] == 0x00
1219 {
1220 return Some(FileType::Dr4);
1221 }
1222
1223 if header.starts_with(b"CANON OPTIONAL DATA\0") {
1225 return Some(FileType::Vrd);
1226 }
1227
1228 if header.len() >= 4 {
1230 let is_le =
1231 header[0] == b'I' && header[1] == b'I' && header[2] == 0x2A && header[3] == 0x00;
1232 let is_be =
1233 header[0] == b'M' && header[1] == b'M' && header[2] == 0x00 && header[3] == 0x2A;
1234 if is_le || is_be {
1235 if header.len() >= 10 && is_le && header[8] == b'C' && header[9] == b'R' {
1237 return Some(FileType::Cr2);
1238 }
1239 if header.len() >= 12 && is_le && &header[8..12] == b"IIII" {
1241 return Some(FileType::Iiq);
1242 }
1243 if header.len() >= 12 && is_be && &header[8..12] == b"MMMM" {
1244 return Some(FileType::Iiq);
1245 }
1246 if header.len() >= 4
1248 && is_le
1249 && header[0] == b'I'
1250 && header[1] == b'I'
1251 && header.len() >= 8
1252 {
1253 }
1256 return Some(FileType::Tiff);
1259 }
1260 let is_btf_le =
1262 header[0] == b'I' && header[1] == b'I' && header[2] == 0x2B && header[3] == 0x00;
1263 let is_btf_be =
1264 header[0] == b'M' && header[1] == b'M' && header[2] == 0x00 && header[3] == 0x2B;
1265 if is_btf_le || is_btf_be {
1266 return Some(FileType::Btf);
1267 }
1268 }
1269
1270 if header.starts_with(b"BM") && header.len() >= 6 {
1272 return Some(FileType::Bmp);
1273 }
1274
1275 if header.len() >= 12 && header.starts_with(b"RIFF") {
1277 match &header[8..12] {
1278 b"WEBP" => return Some(FileType::WebP),
1279 b"AVI " => return Some(FileType::Avi),
1280 b"WAVE" => return Some(FileType::Wav),
1281 _ => {}
1282 }
1283 }
1284
1285 if header.starts_with(b"8BPS") {
1287 return Some(FileType::Psd);
1288 }
1289
1290 if header.len() >= 12 && header.starts_with(&[0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20]) {
1292 return Some(FileType::Jp2);
1293 }
1294
1295 if header.starts_with(&[0xFF, 0x4F, 0xFF, 0x51]) {
1297 return Some(FileType::J2c);
1298 }
1299
1300 if header.len() >= 2 && header[0] == 0xFF && header[1] == 0x0A {
1302 return Some(FileType::Jxl);
1303 }
1304 if header.len() >= 12 && header.starts_with(&[0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x4C, 0x20]) {
1305 return Some(FileType::Jxl);
1306 }
1307
1308 if header.starts_with(b"FLIF") {
1310 return Some(FileType::Flif);
1311 }
1312
1313 if header.starts_with(&[0x42, 0x50, 0x47, 0xFB]) {
1315 return Some(FileType::Bpg);
1316 }
1317
1318 if header.starts_with(&[0x76, 0x2F, 0x31, 0x01]) {
1320 return Some(FileType::Exr);
1321 }
1322
1323 if header.len() >= 4
1325 && header[0] == 0
1326 && header[1] == 0
1327 && (header[2] == 1 || header[2] == 2)
1328 && header[3] == 0
1329 {
1330 return Some(FileType::Ico);
1331 }
1332
1333 if header.len() >= 8 && header.starts_with(b"AT&TFORM") {
1335 return Some(FileType::DjVu);
1336 }
1337
1338 if header.starts_with(b"gimp xcf") {
1340 return Some(FileType::Xcf);
1341 }
1342
1343 if header.starts_with(&[0x8A, 0x4D, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) {
1345 return Some(FileType::Mng);
1346 }
1347
1348 if header.starts_with(&[0x8B, 0x4A, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) {
1350 return Some(FileType::Mng);
1351 }
1352
1353 if header.len() >= 10 && header.starts_with(b"#?RADIANCE") {
1355 return Some(FileType::Hdr);
1356 }
1357
1358 if header.len() >= 3
1360 && header[0] == b'P'
1361 && (header[1] == b'F' || header[1] == b'f')
1362 && header[2] == b'\n'
1363 {
1364 return Some(FileType::PortableFloatMap);
1365 }
1366
1367 if header.starts_with(b"FPF Public Image Format\0") {
1369 return Some(FileType::Fpf);
1370 }
1371
1372 if header.len() >= 15
1374 && header[0] == 0x70
1375 && header[1] == 0x00
1376 && header[2] == 0x00
1377 && header[3] == 0x00
1378 && header[8] == 0x2A
1379 && header[13] == b'<'
1380 && header[14] == 0x00
1381 {
1382 return Some(FileType::Lif);
1383 }
1384
1385 if header.starts_with(b"rawzor") {
1387 return Some(FileType::Rwz);
1388 }
1389
1390 if header.len() >= 4 && header[0] == b'I' && header[1] == b'I' && header[2] == 0xBC {
1392 return Some(FileType::Jxr);
1393 }
1394
1395 if header.len() >= 15 && header.starts_with(b"FUJIFILMCCD-RAW") {
1399 return Some(FileType::Raf);
1400 }
1401
1402 if header.len() >= 14
1404 && header[0] == b'I'
1405 && header[1] == b'I'
1406 && header[2] == 0x1A
1407 && header[3] == 0x00
1408 && &header[6..14] == b"HEAPCCDR"
1409 {
1410 return Some(FileType::Crw);
1411 }
1412
1413 if header.starts_with(&[0x00, 0x4D, 0x52, 0x4D]) {
1415 return Some(FileType::Mrw);
1416 }
1417
1418 if header.starts_with(b"FOVb") {
1420 return Some(FileType::X3f);
1421 }
1422
1423 if header.len() >= 4
1425 && header[0] == b'I'
1426 && header[1] == b'I'
1427 && header[2] == 0x55
1428 && header[3] == 0x00
1429 {
1430 return Some(FileType::Rw2);
1431 }
1432
1433 if header.len() >= 12 && &header[4..8] == b"ftyp" {
1437 let brand = &header[8..12];
1438 if brand == b"heic"
1440 || brand == b"mif1"
1441 || brand == b"heim"
1442 || brand == b"heis"
1443 || brand == b"msf1"
1444 {
1445 return Some(FileType::Heif);
1446 }
1447 if brand == b"avif" || brand == b"avis" {
1449 return Some(FileType::Avif);
1450 }
1451 if brand == b"crx " {
1453 return Some(FileType::Cr3);
1454 }
1455 if brand == b"qt " {
1457 return Some(FileType::QuickTime);
1458 }
1459 if brand == b"3gp4" || brand == b"3gp5" || brand == b"3gp6" || brand == b"3g2a" {
1461 return Some(FileType::ThreeGP);
1462 }
1463 if brand == b"M4A " || brand == b"M4B " || brand == b"M4P " {
1465 return Some(FileType::M4a);
1466 }
1467 if brand == b"M4V " || brand == b"M4VH" || brand == b"M4VP" {
1468 return Some(FileType::Mp4);
1469 }
1470 if brand == b"F4V " || brand == b"F4P " {
1472 return Some(FileType::F4v);
1473 }
1474 return Some(FileType::Mp4);
1476 }
1477
1478 if header.len() >= 8 {
1480 let atom_type = &header[4..8];
1481 if atom_type == b"moov"
1482 || atom_type == b"mdat"
1483 || atom_type == b"wide"
1484 || atom_type == b"free"
1485 || atom_type == b"pnot"
1486 || atom_type == b"skip"
1487 {
1488 return Some(FileType::QuickTime);
1489 }
1490 }
1491
1492 if header.starts_with(&[0x1A, 0x45, 0xDF, 0xA3]) {
1494 return Some(FileType::Mkv);
1495 }
1497
1498 if header.starts_with(b"FLV\x01") {
1500 return Some(FileType::Flv);
1501 }
1502
1503 if header.len() >= 16 && header.starts_with(&[0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11]) {
1505 return Some(FileType::Asf);
1506 }
1508
1509 if header.len() >= 8 && header.starts_with(&[0x06, 0x0E, 0x2B, 0x34]) {
1511 return Some(FileType::Mxf);
1512 }
1513
1514 if header.len() >= 10 && header.starts_with(b"ZISRAWFILE") {
1516 return Some(FileType::Czi);
1517 }
1518
1519 if header.len() >= 40 && &header[36..40] == b"acsp" {
1521 return Some(FileType::Icc);
1522 }
1523
1524 if header.len() >= 4
1526 && header[0] == 0
1527 && header[1] == 0
1528 && header[2] == 1
1529 && (header[3] == 0xBA || header[3] == 0xBB || (header[3] & 0xF0) == 0xE0)
1530 {
1531 return Some(FileType::Mpeg);
1532 }
1533
1534 if !header.is_empty() && header[0] == 0x47 {
1536 if header.len() >= 376 && header[188] == 0x47 {
1537 return Some(FileType::M2ts);
1538 }
1539 if header.len() >= 384 && header[192] == 0x47 {
1540 return Some(FileType::M2ts);
1541 }
1542 }
1543
1544 if header.starts_with(b".RMF") {
1546 return Some(FileType::RealMedia);
1547 }
1548
1549 if header.starts_with(b"RED1") || header.starts_with(b"RED2") {
1551 return Some(FileType::R3d);
1552 }
1553
1554 if header.starts_with(b"ID3") {
1558 return Some(FileType::Mp3);
1559 }
1560 if header.len() >= 2
1564 && header[0] == 0xFF
1565 && (header[1] == 0xF0 || header[1] == 0xF1 || header[1] == 0xF8 || header[1] == 0xF9)
1566 {
1567 return Some(FileType::Aac);
1568 }
1569 if header.len() >= 2 && header[0] == 0xFF && (header[1] & 0xE0) == 0xE0 {
1571 return Some(FileType::Mp3);
1572 }
1573
1574 if header.starts_with(b"fLaC") {
1576 return Some(FileType::Flac);
1577 }
1578
1579 if header.starts_with(b"OggS") {
1581 return Some(FileType::Ogg);
1582 }
1583
1584 if header.len() >= 12
1586 && header.starts_with(b"FORM")
1587 && (&header[8..12] == b"AIFF" || &header[8..12] == b"AIFC")
1588 {
1589 return Some(FileType::Aiff);
1590 }
1591
1592 if header.starts_with(b"MAC ") {
1594 return Some(FileType::Ape);
1595 }
1596
1597 if header.len() >= 0x20 && &header[0x19..0x20] == b"ARECOYK" {
1599 return Some(FileType::KyoceraRaw);
1600 }
1601
1602 if header.starts_with(b"MP+") || header.starts_with(b"MPCK") {
1604 return Some(FileType::Mpc);
1605 }
1606
1607 if header.starts_with(b"wvpk") {
1609 return Some(FileType::WavPack);
1610 }
1611
1612 if header.starts_with(b"DSD ") {
1614 return Some(FileType::Dsf);
1615 }
1616
1617 if header.starts_with(b"OFR ") {
1619 return Some(FileType::Ofr);
1620 }
1621
1622 if header.len() >= 4
1624 && header[0] == b'.'
1625 && header[1] == b'r'
1626 && header[2] == b'a'
1627 && header[3] == 0xFD
1628 {
1629 return Some(FileType::RealAudio);
1630 }
1631
1632 if header.len() >= 4
1634 && (header[0] == 0x02 || header[0] == 0x03)
1635 && (header[1] == b'd')
1636 && (header[2] == b's')
1637 && (header[3] == b's' || header[3] == b'2')
1638 {
1639 return Some(FileType::Dss);
1640 }
1641
1642 if header.starts_with(b"%PDF-") {
1646 return Some(FileType::Pdf);
1647 }
1648
1649 if header.starts_with(b"StartFontMetrics")
1651 || header.starts_with(b"StartCompFontMetrics")
1652 || header.starts_with(b"StartMasterFontMetrics")
1653 {
1654 return Some(FileType::Afm);
1655 }
1656
1657 if header.starts_with(b"%!PS-AdobeFont-")
1660 || header.starts_with(b"%!PS-Bitstream ")
1661 || header.starts_with(b"%!FontType1-")
1662 {
1663 return Some(FileType::Pfa);
1664 }
1665
1666 if header.len() >= 21
1668 && header[0] == 0x80
1669 && header[1] == 0x01
1670 && (header[6..].starts_with(b"%!PS-AdobeFont-")
1671 || header[6..].starts_with(b"%!PS-Bitstream ")
1672 || header[6..].starts_with(b"%!FontType1-"))
1673 {
1674 return Some(FileType::Pfb);
1675 }
1676
1677 if header.starts_with(&[0xC5, 0xD0, 0xD3, 0xC6]) {
1679 return Some(FileType::Eps);
1680 }
1681 if header.starts_with(b"%!PS-Adobe-")
1682 && header[..header.len().min(32)]
1683 .windows(4)
1684 .any(|w| w == b"EPSF")
1685 {
1686 return Some(FileType::Eps);
1687 }
1688
1689 if header.starts_with(b"%!PS") || header.starts_with(b"%!Adobe") {
1691 return Some(FileType::PostScript);
1692 }
1693
1694 if header.starts_with(b"id=ImageMagick") {
1696 return Some(FileType::Miff);
1697 }
1698
1699 if header.starts_with(&[0x78, 0x9f, 0x3e, 0x22]) {
1701 return Some(FileType::Tnef);
1702 }
1703
1704 if header.starts_with(&[0xff, 0x57, 0x50, 0x43]) {
1706 return Some(FileType::Wpg);
1707 }
1708
1709 if header.len() >= 4
1711 && header[0] == 0x1f
1712 && header[1] == 0x07
1713 && header[2] == 0x00
1714 && (header[3] == 0x3f || header[3] == 0xbf)
1715 {
1716 return Some(FileType::Dv);
1717 }
1718
1719 if header.len() >= 8 && &header[4..8] == b"itch" {
1721 return Some(FileType::Itc);
1722 }
1723
1724 if header.starts_with(&[0xD0, 0xCF, 0x11, 0xE0]) {
1726 return Some(FileType::Doc); }
1728
1729 if header.starts_with(b"{\\rtf") {
1731 return Some(FileType::Rtf);
1732 }
1733
1734 if header.len() >= 8 && header.starts_with(&[0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5]) {
1736 return Some(FileType::InDesign);
1737 }
1738
1739 if header.starts_with(&[0x50, 0x4B, 0x03, 0x04]) {
1743 return Some(FileType::Zip);
1744 }
1746
1747 if header.len() >= 6 && header.starts_with(b"Rar!\x1A\x07") {
1749 return Some(FileType::Rar);
1750 }
1751
1752 if header.len() >= 6 && header.starts_with(&[0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]) {
1754 return Some(FileType::SevenZ);
1755 }
1756
1757 if header.len() >= 2 && header[0] == 0x1F && header[1] == 0x8B {
1759 return Some(FileType::Gzip);
1760 }
1761
1762 if header.len() >= 4
1764 && header[0] == 0x0A
1765 && header[1] == 0x0D
1766 && header[2] == 0x0D
1767 && header[3] == 0x0A
1768 {
1769 return Some(FileType::Pcapng);
1770 }
1771
1772 if header.len() >= 4
1774 && ((header[0] == 0xD4 && header[1] == 0xC3 && header[2] == 0xB2 && header[3] == 0xA1)
1775 || (header[0] == 0xA1 && header[1] == 0xB2 && header[2] == 0xC3 && header[3] == 0xD4))
1776 {
1777 return Some(FileType::Pcap);
1778 }
1779
1780 if header.len() >= 3
1784 && ((header[0] == b'F' || header[0] == b'C' || header[0] == b'Z')
1785 && header[1] == b'W'
1786 && header[2] == b'S')
1787 {
1788 return Some(FileType::Swf);
1789 }
1790
1791 if header.len() >= 132 && &header[128..132] == b"DICM" {
1793 return Some(FileType::Dicom);
1794 }
1795
1796 if header.len() >= 214 {
1798 let ax1 = u32::from_le_bytes([header[64], header[65], header[66], header[67]]);
1799 let ax2 = u32::from_le_bytes([header[68], header[69], header[70], header[71]]);
1800 let ax3 = u32::from_le_bytes([header[72], header[73], header[74], header[75]]);
1801 if (1..=3).contains(&ax1)
1802 && (1..=3).contains(&ax2)
1803 && (1..=3).contains(&ax3)
1804 && &header[208..211] == b"MAP"
1805 {
1806 let ms0 = header[212];
1807 let ms1 = header[213];
1808 if (ms1 == 0x41 || ms1 == 0x44) && ms0 == 0x44 || (ms0 == 0x11 && ms1 == 0x11) {
1809 return Some(FileType::Mrc);
1810 }
1811 }
1812 }
1813
1814 if header.len() >= 12 && &header[8..12] == b".FIT" {
1817 return Some(FileType::Fit);
1818 }
1819
1820 if header.len() >= 9 && header.starts_with(b"SIMPLE =") {
1822 return Some(FileType::Fits);
1823 }
1824
1825 if header.len() >= 4 && header[0] == 0x7E && header[1] == 0x10 && header[2] == 0x04 {
1827 return Some(FileType::Mie);
1828 }
1829
1830 if header.starts_with(b"<?xpacket") || header.starts_with(b"<x:xmpmeta") {
1832 return Some(FileType::Xmp);
1833 }
1834
1835 if header.starts_with(b"<?xml") || header.starts_with(b"<svg") {
1837 let preview = &header[..header.len().min(512)];
1838 if preview.windows(4).any(|w| w == b"<svg") {
1839 return Some(FileType::Svg);
1840 }
1841 if preview.windows(5).any(|w| w == b"<html" || w == b"<HTML") {
1842 return Some(FileType::Html); }
1844 if preview.windows(10).any(|w| w == b"<x:xmpmeta")
1845 || preview.windows(9).any(|w| w == b"<?xpacket")
1846 {
1847 return Some(FileType::Xmp);
1848 }
1849 if preview.windows(4).any(|w| w == b"<rdf" || w == b"<RDF") {
1850 return Some(FileType::Xmp);
1851 }
1852 if preview.windows(7).any(|w| w == b"<plist")
1854 || preview.windows(20).any(|w| w == b"DTD PLIST")
1855 {
1856 return Some(FileType::Plist);
1857 }
1858 if preview.windows(5).any(|w| w == b"<?aid") {
1860 return Some(FileType::Inx);
1861 }
1862 return Some(FileType::Xml);
1864 }
1865
1866 if header.starts_with(b"<!DOCTYPE html")
1868 || header.starts_with(b"<!doctype html")
1869 || header.starts_with(b"<!DOCTYPE HTML")
1870 || header.starts_with(b"<html")
1871 || header.starts_with(b"<HTML")
1872 {
1873 return Some(FileType::Html);
1874 }
1875
1876 if header.starts_with(&[0x7F, b'E', b'L', b'F']) {
1878 return Some(FileType::Exe);
1879 }
1880
1881 if header.starts_with(&[0xFE, 0xED, 0xFA, 0xCE])
1883 || header.starts_with(&[0xCE, 0xFA, 0xED, 0xFE])
1884 {
1885 return Some(FileType::Exe);
1886 }
1887
1888 if header.starts_with(&[0xFE, 0xED, 0xFA, 0xCF])
1890 || header.starts_with(&[0xCF, 0xFA, 0xED, 0xFE])
1891 {
1892 return Some(FileType::Exe);
1893 }
1894
1895 if header.starts_with(&[0xCA, 0xFE, 0xBA, 0xBE]) {
1897 return Some(FileType::Exe);
1898 }
1899
1900 if header.starts_with(b"MZ") {
1902 return Some(FileType::Exe);
1903 }
1904
1905 if (header.starts_with(&[0x00, 0x01, 0x00, 0x00])
1907 || header.starts_with(b"true")
1908 || header.starts_with(b"typ1"))
1909 && header.len() >= 12
1910 {
1911 return Some(FileType::Font);
1912 }
1913
1914 if header.starts_with(b"ttcf") {
1916 return Some(FileType::Font);
1917 }
1918
1919 if header.starts_with(b"OTTO") {
1921 return Some(FileType::Font);
1922 }
1923
1924 if header.starts_with(b"wOFF") {
1926 return Some(FileType::Font);
1927 }
1928
1929 if header.starts_with(b"wOF2") {
1931 return Some(FileType::Font);
1932 }
1933
1934 if header.len() >= 2 && header[0] == b'V' && header[1] == b'6' {
1936 return Some(FileType::Moi);
1937 }
1938
1939 if header.starts_with(b"PGF") {
1941 return Some(FileType::Pgf);
1942 }
1943
1944 if header.starts_with(b"XISF0100") {
1946 return Some(FileType::Xisf);
1947 }
1948
1949 if header.len() >= 27 && header.starts_with(b"Paint Shop Pro Image File\n\x1a") {
1951 return Some(FileType::Psp);
1952 }
1953
1954 if header.len() >= 12
1957 && header[8] == 0x00
1958 && header[9] == 0x00
1959 && header[10] == 0x00
1960 && header[11] == 0x7C
1961 {
1962 return Some(FileType::SonyPmp);
1963 }
1964
1965 None
1966}
1967
1968pub fn detect_from_extension(ext: &str) -> Option<FileType> {
1970 let ext_lower = ext.to_ascii_lowercase();
1971 let ext_lower = ext_lower.trim_start_matches('.');
1972
1973 for &ft in ALL_FILE_TYPES {
1974 for known_ext in ft.extensions() {
1975 if ext_lower == *known_ext {
1976 return Some(ft);
1977 }
1978 }
1979 }
1980
1981 None
1982}
1983
1984impl std::fmt::Display for FileType {
1985 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1986 write!(f, "{}", self.description())
1987 }
1988}
1989
1990impl std::fmt::Display for Support {
1991 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1992 match self {
1993 Support::Read => write!(f, "R"),
1994 Support::ReadWrite => write!(f, "R/W"),
1995 Support::ReadWriteCreate => write!(f, "R/W/C"),
1996 }
1997 }
1998}
1999
2000#[cfg(test)]
2001mod tests {
2002 use super::*;
2003
2004 #[test]
2005 fn test_detect_jpeg() {
2006 let header = [0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, b'J', b'F', b'I', b'F'];
2007 assert_eq!(detect_from_magic(&header), Some(FileType::Jpeg));
2008 }
2009
2010 #[test]
2011 fn test_detect_png() {
2012 let header = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
2013 assert_eq!(detect_from_magic(&header), Some(FileType::Png));
2014 }
2015
2016 #[test]
2017 fn test_detect_tiff_le() {
2018 let header = [b'I', b'I', 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00];
2019 assert_eq!(detect_from_magic(&header), Some(FileType::Tiff));
2020 }
2021
2022 #[test]
2023 fn test_detect_tiff_be() {
2024 let header = [b'M', b'M', 0x00, 0x2A, 0x00, 0x00, 0x00, 0x08];
2025 assert_eq!(detect_from_magic(&header), Some(FileType::Tiff));
2026 }
2027
2028 #[test]
2029 fn test_detect_cr2() {
2030 let header = [b'I', b'I', 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, b'C', b'R'];
2031 assert_eq!(detect_from_magic(&header), Some(FileType::Cr2));
2032 }
2033
2034 #[test]
2035 fn test_detect_pdf() {
2036 let header = b"%PDF-1.7 some more data here";
2037 assert_eq!(detect_from_magic(header), Some(FileType::Pdf));
2038 }
2039
2040 #[test]
2041 fn test_detect_webp() {
2042 let header = b"RIFF\x00\x00\x00\x00WEBP";
2043 assert_eq!(detect_from_magic(header), Some(FileType::WebP));
2044 }
2045
2046 #[test]
2047 fn test_detect_heif() {
2048 let mut header = [0u8; 16];
2049 header[4..8].copy_from_slice(b"ftyp");
2050 header[8..12].copy_from_slice(b"heic");
2051 assert_eq!(detect_from_magic(&header), Some(FileType::Heif));
2052 }
2053
2054 #[test]
2055 fn test_detect_avif() {
2056 let mut header = [0u8; 16];
2057 header[4..8].copy_from_slice(b"ftyp");
2058 header[8..12].copy_from_slice(b"avif");
2059 assert_eq!(detect_from_magic(&header), Some(FileType::Avif));
2060 }
2061
2062 #[test]
2063 fn test_detect_cr3() {
2064 let mut header = [0u8; 16];
2065 header[4..8].copy_from_slice(b"ftyp");
2066 header[8..12].copy_from_slice(b"crx ");
2067 assert_eq!(detect_from_magic(&header), Some(FileType::Cr3));
2068 }
2069
2070 #[test]
2071 fn test_detect_flac() {
2072 assert_eq!(detect_from_magic(b"fLaC\x00\x00"), Some(FileType::Flac));
2073 }
2074
2075 #[test]
2076 fn test_detect_ogg() {
2077 assert_eq!(detect_from_magic(b"OggS\x00\x02"), Some(FileType::Ogg));
2078 }
2079
2080 #[test]
2081 fn test_detect_mp3_id3() {
2082 assert_eq!(detect_from_magic(b"ID3\x04\x00"), Some(FileType::Mp3));
2083 }
2084
2085 #[test]
2086 fn test_detect_rar() {
2087 assert_eq!(
2088 detect_from_magic(b"Rar!\x1A\x07\x01\x00"),
2089 Some(FileType::Rar)
2090 );
2091 }
2092
2093 #[test]
2094 fn test_detect_7z() {
2095 assert_eq!(
2096 detect_from_magic(&[0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]),
2097 Some(FileType::SevenZ)
2098 );
2099 }
2100
2101 #[test]
2102 fn test_detect_gzip() {
2103 assert_eq!(
2104 detect_from_magic(&[0x1F, 0x8B, 0x08, 0x00]),
2105 Some(FileType::Gzip)
2106 );
2107 }
2108
2109 #[test]
2110 fn test_detect_raf() {
2111 assert_eq!(
2112 detect_from_magic(b"FUJIFILMCCD-RAW 0201"),
2113 Some(FileType::Raf)
2114 );
2115 }
2116
2117 #[test]
2118 fn test_detect_psd() {
2119 assert_eq!(detect_from_magic(b"8BPS\x00\x01"), Some(FileType::Psd));
2120 }
2121
2122 #[test]
2123 fn test_detect_from_extension() {
2124 assert_eq!(detect_from_extension("jpg"), Some(FileType::Jpeg));
2125 assert_eq!(detect_from_extension(".JPEG"), Some(FileType::Jpeg));
2126 assert_eq!(detect_from_extension("cr2"), Some(FileType::Cr2));
2127 assert_eq!(detect_from_extension("cr3"), Some(FileType::Cr3));
2128 assert_eq!(detect_from_extension("nef"), Some(FileType::Nef));
2129 assert_eq!(detect_from_extension("arw"), Some(FileType::Arw));
2130 assert_eq!(detect_from_extension("dng"), Some(FileType::Dng));
2131 assert_eq!(detect_from_extension("raf"), Some(FileType::Raf));
2132 assert_eq!(detect_from_extension("mp4"), Some(FileType::Mp4));
2133 assert_eq!(detect_from_extension("mov"), Some(FileType::QuickTime));
2134 assert_eq!(detect_from_extension("flac"), Some(FileType::Flac));
2135 assert_eq!(detect_from_extension("docx"), Some(FileType::Docx));
2136 assert_eq!(detect_from_extension("xlsx"), Some(FileType::Xlsx));
2137 assert_eq!(detect_from_extension("3fr"), Some(FileType::ThreeFR));
2138 assert_eq!(detect_from_extension("xyz"), None);
2139 }
2140
2141 #[test]
2142 fn test_all_types_have_extensions() {
2143 for &ft in FileType::all() {
2144 assert!(!ft.extensions().is_empty(), "{:?} has no extensions", ft);
2145 }
2146 }
2147
2148 #[test]
2149 fn test_all_types_have_mime() {
2150 for &ft in FileType::all() {
2151 assert!(!ft.mime_type().is_empty(), "{:?} has no MIME type", ft);
2152 }
2153 }
2154
2155 #[test]
2156 fn test_total_format_count() {
2157 assert!(
2158 FileType::all().len() >= 100,
2159 "Expected 100+ formats, got {}",
2160 FileType::all().len()
2161 );
2162 }
2163
2164 #[test]
2165 fn test_detect_mp4_ftyp_isom() {
2166 let mut header = [0u8; 16];
2167 header[0..4].copy_from_slice(&[0x00, 0x00, 0x00, 0x10]);
2169 header[4..8].copy_from_slice(b"ftyp");
2170 header[8..12].copy_from_slice(b"isom");
2171 assert_eq!(detect_from_magic(&header), Some(FileType::Mp4));
2172 }
2173
2174 #[test]
2175 fn test_detect_mp4_ftyp_mp42() {
2176 let mut header = [0u8; 16];
2177 header[0..4].copy_from_slice(&[0x00, 0x00, 0x00, 0x10]);
2178 header[4..8].copy_from_slice(b"ftyp");
2179 header[8..12].copy_from_slice(b"mp42");
2180 assert_eq!(detect_from_magic(&header), Some(FileType::Mp4));
2181 }
2182
2183 #[test]
2184 fn test_detect_mkv_ebml() {
2185 let header = [0x1A, 0x45, 0xDF, 0xA3, 0x93, 0x42, 0x82, 0x88];
2187 assert_eq!(detect_from_magic(&header), Some(FileType::Mkv));
2188 }
2189
2190 #[test]
2191 fn test_detect_flif() {
2192 assert_eq!(
2193 detect_from_magic(b"FLIF\x30\x00\x01\x00"),
2194 Some(FileType::Flif)
2195 );
2196 }
2197
2198 #[test]
2199 fn test_detect_bpg() {
2200 assert_eq!(
2201 detect_from_magic(&[0x42, 0x50, 0x47, 0xFB, 0x00, 0x00]),
2202 Some(FileType::Bpg)
2203 );
2204 }
2205
2206 #[test]
2207 fn test_detect_exe_mz() {
2208 assert_eq!(
2210 detect_from_magic(b"MZ\x90\x00\x03\x00\x00\x00"),
2211 Some(FileType::Exe)
2212 );
2213 }
2214
2215 #[test]
2216 fn test_detect_elf() {
2217 assert_eq!(
2218 detect_from_magic(&[0x7F, b'E', b'L', b'F', 0x02, 0x01]),
2219 Some(FileType::Exe)
2220 );
2221 }
2222
2223 #[test]
2224 fn test_detect_macho_64_le() {
2225 assert_eq!(
2227 detect_from_magic(&[0xCF, 0xFA, 0xED, 0xFE, 0x07, 0x00]),
2228 Some(FileType::Exe)
2229 );
2230 }
2231
2232 #[test]
2233 fn test_detect_macho_32_be() {
2234 assert_eq!(
2236 detect_from_magic(&[0xFE, 0xED, 0xFA, 0xCE, 0x00, 0x00]),
2237 Some(FileType::Exe)
2238 );
2239 }
2240
2241 #[test]
2242 fn test_detect_macho_fat() {
2243 assert_eq!(
2245 detect_from_magic(&[0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00]),
2246 Some(FileType::Exe)
2247 );
2248 }
2249
2250 #[test]
2251 fn test_detect_dicom() {
2252 let mut header = vec![0u8; 136];
2254 header[128..132].copy_from_slice(b"DICM");
2255 assert_eq!(detect_from_magic(&header), Some(FileType::Dicom));
2256 }
2257}