filetype.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. //! Tests for various types of file (video, image, compressed, etc).
  2. //!
  3. //! Currently this is dependent on the file’s name and extension, because
  4. //! those are the only metadata that we have access to without reading the
  5. //! file’s contents.
  6. //!
  7. //! # Contributors
  8. //! Please keep these lists sorted. If you're using vim, :sort i
  9. use phf::{phf_map, Map};
  10. use crate::fs::File;
  11. #[derive(Debug, Clone)]
  12. pub enum FileType {
  13. Image,
  14. Video,
  15. Music,
  16. Lossless, // Lossless music, rather than any other kind of data...
  17. Crypto,
  18. Document,
  19. Compressed,
  20. Temp,
  21. Compiled,
  22. Build, // A “build file is something that can be run or activated somehow in order to
  23. // kick off the build of a project. It’s usually only present in directories full of
  24. // source code.
  25. Source,
  26. }
  27. /// Mapping from full filenames to file type.
  28. const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
  29. /* Immediate file - kick off the build of a project */
  30. "Brewfile" => FileType::Build,
  31. "bsconfig.json" => FileType::Build,
  32. "BUILD" => FileType::Build,
  33. "BUILD.bazel" => FileType::Build,
  34. "build.gradle" => FileType::Build,
  35. "build.sbt" => FileType::Build,
  36. "build.xml" => FileType::Build,
  37. "Cargo.toml" => FileType::Build,
  38. "CMakeLists.txt" => FileType::Build,
  39. "composer.json" => FileType::Build,
  40. "configure" => FileType::Build,
  41. "Containerfile" => FileType::Build,
  42. "Dockerfile" => FileType::Build,
  43. "Earthfile" => FileType::Build,
  44. "flake.nix" => FileType::Build,
  45. "Gemfile" => FileType::Build,
  46. "GNUmakefile" => FileType::Build,
  47. "Gruntfile.coffee" => FileType::Build,
  48. "Gruntfile.js" => FileType::Build,
  49. "jsconfig.json" => FileType::Build,
  50. "Justfile" => FileType::Build,
  51. "justfile" => FileType::Build,
  52. "Makefile" => FileType::Build,
  53. "makefile" => FileType::Build,
  54. "meson.build" => FileType::Build,
  55. "mix.exs" => FileType::Build,
  56. "package.json" => FileType::Build,
  57. "Pipfile" => FileType::Build,
  58. "PKGBUILD" => FileType::Build,
  59. "Podfile" => FileType::Build,
  60. "pom.xml" => FileType::Build,
  61. "Procfile" => FileType::Build,
  62. "pyproject.toml" => FileType::Build,
  63. "Rakefile" => FileType::Build,
  64. "RoboFile.php" => FileType::Build,
  65. "SConstruct" => FileType::Build,
  66. "tsconfig.json" => FileType::Build,
  67. "Vagrantfile" => FileType::Build,
  68. "webpack.config.cjs" => FileType::Build,
  69. "webpack.config.js" => FileType::Build,
  70. "WORKSPACE" => FileType::Build,
  71. /* Cryptology files */
  72. "id_dsa" => FileType::Crypto,
  73. "id_ecdsa" => FileType::Crypto,
  74. "id_ecdsa_sk" => FileType::Crypto,
  75. "id_ed25519" => FileType::Crypto,
  76. "id_ed25519_sk" => FileType::Crypto,
  77. "id_rsa" => FileType::Crypto,
  78. };
  79. /// Mapping from lowercase file extension to file type. If an image, video, music, or lossless
  80. /// extension is added also update the extension icon map.
  81. const EXTENSION_TYPES: Map<&'static str, FileType> = phf_map! {
  82. /* Immediate file - kick off the build of a project */
  83. "ninja" => FileType::Build,
  84. /* Image files */
  85. "arw" => FileType::Image,
  86. "avif" => FileType::Image,
  87. "bmp" => FileType::Image,
  88. "cbr" => FileType::Image,
  89. "cbz" => FileType::Image,
  90. "cr2" => FileType::Image,
  91. "dvi" => FileType::Image,
  92. "eps" => FileType::Image,
  93. "gif" => FileType::Image,
  94. "heic" => FileType::Image,
  95. "heif" => FileType::Image,
  96. "ico" => FileType::Image,
  97. "j2c" => FileType::Image,
  98. "j2k" => FileType::Image,
  99. "jfi" => FileType::Image,
  100. "jfif" => FileType::Image,
  101. "jif" => FileType::Image,
  102. "jp2" => FileType::Image,
  103. "jpe" => FileType::Image,
  104. "jpeg" => FileType::Image,
  105. "jpf" => FileType::Image,
  106. "jpg" => FileType::Image,
  107. "jpx" => FileType::Image,
  108. "jxl" => FileType::Image,
  109. "nef" => FileType::Image,
  110. "orf" => FileType::Image,
  111. "pbm" => FileType::Image,
  112. "pgm" => FileType::Image,
  113. "png" => FileType::Image,
  114. "pnm" => FileType::Image,
  115. "ppm" => FileType::Image,
  116. "ps" => FileType::Image,
  117. "psd" => FileType::Image,
  118. "pxm" => FileType::Image,
  119. "raw" => FileType::Image,
  120. "qoi" => FileType::Image,
  121. "stl" => FileType::Image,
  122. "svg" => FileType::Image,
  123. "tif" => FileType::Image,
  124. "tiff" => FileType::Image,
  125. "webp" => FileType::Image,
  126. "xcf" => FileType::Image,
  127. "xpm" => FileType::Image,
  128. /* Video files */
  129. "avi" => FileType::Video,
  130. "flv" => FileType::Video,
  131. "h264" => FileType::Video,
  132. "heics" => FileType::Video,
  133. "m2ts" => FileType::Video,
  134. "m2v" => FileType::Video,
  135. "m4v" => FileType::Video,
  136. "mkv" => FileType::Video,
  137. "mov" => FileType::Video,
  138. "mp4" => FileType::Video,
  139. "mpeg" => FileType::Video,
  140. "mpg" => FileType::Video,
  141. "ogm" => FileType::Video,
  142. "ogv" => FileType::Video,
  143. "video" => FileType::Video,
  144. "vob" => FileType::Video,
  145. "webm" => FileType::Video,
  146. "wmv" => FileType::Video,
  147. /* Music files */
  148. "aac" => FileType::Music, // Advanced Audio Coding
  149. "m4a" => FileType::Music,
  150. "mka" => FileType::Music,
  151. "mp2" => FileType::Music,
  152. "mp3" => FileType::Music,
  153. "ogg" => FileType::Music,
  154. "opus" => FileType::Music,
  155. "wma" => FileType::Music,
  156. /* Lossless music, rather than any other kind of data... */
  157. "aif" => FileType::Lossless,
  158. "aifc" => FileType::Lossless,
  159. "aiff" => FileType::Lossless,
  160. "alac" => FileType::Lossless,
  161. "ape" => FileType::Lossless,
  162. "flac" => FileType::Lossless,
  163. "pcm" => FileType::Lossless,
  164. "wav" => FileType::Lossless,
  165. "wv" => FileType::Lossless,
  166. /* Cryptology files */
  167. "asc" => FileType::Crypto, // GnuPG ASCII armored file
  168. "cer" => FileType::Crypto,
  169. "crt" => FileType::Crypto,
  170. "csr" => FileType::Crypto, // PKCS#10 Certificate Signing Request
  171. "gpg" => FileType::Crypto, // GnuPG encrypted file
  172. "kbx" => FileType::Crypto, // GnuPG keybox
  173. "md5" => FileType::Crypto, // MD5 checksum
  174. "p12" => FileType::Crypto, // PKCS#12 certificate (Netscape)
  175. "pem" => FileType::Crypto, // Privacy-Enhanced Mail certificate
  176. "pfx" => FileType::Crypto, // PKCS#12 certificate (Microsoft)
  177. "pgp" => FileType::Crypto, // PGP security key
  178. "pub" => FileType::Crypto, // Public key
  179. "sha1" => FileType::Crypto, // SHA-1 hash
  180. "sha224" => FileType::Crypto, // SHA-224 hash
  181. "sha256" => FileType::Crypto, // SHA-256 hash
  182. "sha384" => FileType::Crypto, // SHA-384 hash
  183. "sha512" => FileType::Crypto, // SHA-512 hash
  184. "sig" => FileType::Crypto, // GnuPG signed file
  185. "signature" => FileType::Crypto, // e-Filing Digital Signature File (India)
  186. /* Document files */
  187. "djvu" => FileType::Document,
  188. "doc" => FileType::Document,
  189. "docx" => FileType::Document,
  190. "eml" => FileType::Document,
  191. "fotd" => FileType::Document,
  192. "gdoc" => FileType::Document,
  193. "key" => FileType::Document,
  194. "keynote" => FileType::Document,
  195. "numbers" => FileType::Document,
  196. "odp" => FileType::Document,
  197. "ods" => FileType::Document,
  198. "odt" => FileType::Document,
  199. "pages" => FileType::Document,
  200. "pdf" => FileType::Document,
  201. "ppt" => FileType::Document,
  202. "pptx" => FileType::Document,
  203. "rtf" => FileType::Document, // Rich Text Format
  204. "xls" => FileType::Document,
  205. "xlsm" => FileType::Document,
  206. "xlsx" => FileType::Document,
  207. /* Compressed/archive files */
  208. "7z" => FileType::Compressed, // 7-Zip
  209. "ar" => FileType::Compressed,
  210. "arj" => FileType::Compressed,
  211. "br" => FileType::Compressed, // Brotli
  212. "bz" => FileType::Compressed, // bzip
  213. "bz2" => FileType::Compressed, // bzip2
  214. "bz3" => FileType::Compressed, // bzip3
  215. "cpio" => FileType::Compressed,
  216. "deb" => FileType::Compressed, // Debian
  217. "dmg" => FileType::Compressed,
  218. "gz" => FileType::Compressed, // gzip
  219. "iso" => FileType::Compressed,
  220. "lz" => FileType::Compressed,
  221. "lz4" => FileType::Compressed,
  222. "lzh" => FileType::Compressed,
  223. "lzma" => FileType::Compressed,
  224. "lzo" => FileType::Compressed,
  225. "phar" => FileType::Compressed, // PHP PHAR
  226. "qcow" => FileType::Compressed,
  227. "qcow2" => FileType::Compressed,
  228. "rar" => FileType::Compressed,
  229. "rpm" => FileType::Compressed,
  230. "tar" => FileType::Compressed,
  231. "taz" => FileType::Compressed,
  232. "tbz" => FileType::Compressed,
  233. "tbz2" => FileType::Compressed,
  234. "tc" => FileType::Compressed,
  235. "tgz" => FileType::Compressed,
  236. "tlz" => FileType::Compressed,
  237. "txz" => FileType::Compressed,
  238. "tz" => FileType::Compressed,
  239. "xz" => FileType::Compressed,
  240. "vdi" => FileType::Compressed,
  241. "vhd" => FileType::Compressed,
  242. "vhdx" => FileType::Compressed,
  243. "vmdk" => FileType::Compressed,
  244. "z" => FileType::Compressed,
  245. "zip" => FileType::Compressed,
  246. "zst" => FileType::Compressed, // Zstandard
  247. /* Temporary files */
  248. "bak" => FileType::Temp,
  249. "bk" => FileType::Temp,
  250. "bkp" => FileType::Temp,
  251. "crdownload" => FileType::Temp,
  252. "download" => FileType::Temp,
  253. "fdmdownload"=> FileType::Temp,
  254. "part" => FileType::Temp,
  255. "swn" => FileType::Temp,
  256. "swo" => FileType::Temp,
  257. "swp" => FileType::Temp,
  258. "tmp" => FileType::Temp,
  259. /* Compiler output files */
  260. "a" => FileType::Compiled, // Unix static library
  261. "bundle" => FileType::Compiled, // macOS application bundle
  262. "class" => FileType::Compiled, // Java class file
  263. "cma" => FileType::Compiled, // OCaml bytecode library
  264. "cmi" => FileType::Compiled, // OCaml interface
  265. "cmo" => FileType::Compiled, // OCaml bytecode object
  266. "cmx" => FileType::Compiled, // OCaml bytecode object for inlining
  267. "dll" => FileType::Compiled, // Windows dynamic link library
  268. "dylib" => FileType::Compiled, // Mach-O dynamic library
  269. "elc" => FileType::Compiled, // Emacs compiled lisp
  270. "ko" => FileType::Compiled, // Linux kernel module
  271. "lib" => FileType::Compiled, // Windows static library
  272. "o" => FileType::Compiled, // Compiled object file
  273. "obj" => FileType::Compiled, // Compiled object file
  274. "pyc" => FileType::Compiled, // Python compiled code
  275. "pyd" => FileType::Compiled, // Python dynamic module
  276. "pyo" => FileType::Compiled, // Python optimized code
  277. "so" => FileType::Compiled, // Unix shared library
  278. "zwc" => FileType::Compiled, // zsh compiled file
  279. /* Source code */
  280. "applescript"=> FileType::Source, // Apple script
  281. "as" => FileType::Source, // Action script
  282. "asa" => FileType::Source, // asp
  283. "awk" => FileType::Source, // awk
  284. "c" => FileType::Source, // C/C++
  285. "c++" => FileType::Source, // C/C++
  286. "cabal" => FileType::Source, // Cabal
  287. "cc" => FileType::Source, // C/C++
  288. "clj" => FileType::Source, // Clojure
  289. "cp" => FileType::Source, // C/C++ Xcode
  290. "cpp" => FileType::Source, // C/C++
  291. "cr" => FileType::Source, // Crystal
  292. "cs" => FileType::Source, // C#
  293. "css" => FileType::Source, // css
  294. "csx" => FileType::Source, // C#
  295. "cu" => FileType::Source, // CUDA
  296. "cxx" => FileType::Source, // C/C++
  297. "cypher" => FileType::Source, // Cypher (query language)
  298. "d" => FileType::Source, // D
  299. "dart" => FileType::Source, // Dart
  300. "di" => FileType::Source, // D
  301. "dpr" => FileType::Source, // Delphi Pascal
  302. "el" => FileType::Source, // Lisp
  303. "elm" => FileType::Source, // Elm
  304. "erl" => FileType::Source, // Erlang
  305. "ex" => FileType::Source, // Elixir
  306. "exs" => FileType::Source, // Elixir
  307. "fs" => FileType::Source, // F#
  308. "fsh" => FileType::Source, // Fragment shader
  309. "fsi" => FileType::Source, // F#
  310. "fsx" => FileType::Source, // F#
  311. "go" => FileType::Source, // Go
  312. "gradle" => FileType::Source, // Gradle
  313. "groovy" => FileType::Source, // Groovy
  314. "gvy" => FileType::Source, // Groovy
  315. "h" => FileType::Source, // C/C++ header
  316. "h++" => FileType::Source, // C/C++ header
  317. "hpp" => FileType::Source, // C/C++ header
  318. "hs" => FileType::Source, // Haskell
  319. "htc" => FileType::Source, // JavaScript
  320. "hxx" => FileType::Source, // C/C++ header
  321. "inc" => FileType::Source,
  322. "inl" => FileType::Source, // C/C++ Microsoft
  323. "ipynb" => FileType::Source, // Jupyter Notebook
  324. "java" => FileType::Source, // Java
  325. "jl" => FileType::Source, // Julia
  326. "js" => FileType::Source, // JavaScript
  327. "jsx" => FileType::Source, // React
  328. "kt" => FileType::Source, // Kotlin
  329. "kts" => FileType::Source, // Kotlin
  330. "kusto" => FileType::Source, // Kusto (query language)
  331. "less" => FileType::Source, // less
  332. "lhs" => FileType::Source, // Haskell
  333. "lisp" => FileType::Source, // Lisp
  334. "ltx" => FileType::Source, // LaTeX
  335. "lua" => FileType::Source, // Lua
  336. "m" => FileType::Source, // Matlab
  337. "malloy" => FileType::Source, // Malloy (query language)
  338. "matlab" => FileType::Source, // Matlab
  339. "ml" => FileType::Source, // OCaml
  340. "mli" => FileType::Source, // OCaml
  341. "mn" => FileType::Source, // Matlab
  342. "nb" => FileType::Source, // Mathematica
  343. "p" => FileType::Source, // Pascal
  344. "pas" => FileType::Source, // Pascal
  345. "php" => FileType::Source, // PHP
  346. "pl" => FileType::Source, // Perl
  347. "pm" => FileType::Source, // Perl
  348. "pod" => FileType::Source, // Perl
  349. "pp" => FileType::Source, // Puppet
  350. "prql" => FileType::Source, // PRQL
  351. "ps1" => FileType::Source, // PowerShell
  352. "psd1" => FileType::Source, // PowerShell
  353. "psm1" => FileType::Source, // PowerShell
  354. "purs" => FileType::Source, // PureScript
  355. "py" => FileType::Source, // Python
  356. "r" => FileType::Source, // R
  357. "rb" => FileType::Source, // Ruby
  358. "rs" => FileType::Source, // Rust
  359. "rq" => FileType::Source, // SPARQL (query language)
  360. "sass" => FileType::Source, // Sass
  361. "scala" => FileType::Source, // Scala
  362. "scss" => FileType::Source, // Sass
  363. "sql" => FileType::Source, // SQL
  364. "swift" => FileType::Source, // Swift
  365. "tcl" => FileType::Source, // TCL
  366. "tex" => FileType::Source, // LaTeX
  367. "ts" => FileType::Source, // TypeScript
  368. "v" => FileType::Source, // V
  369. "vb" => FileType::Source, // Visual Basic
  370. "vsh" => FileType::Source, // Vertex shader
  371. "zig" => FileType::Source, // Zig
  372. };
  373. impl FileType {
  374. /// Lookup the file type based on the file's name, by the file name
  375. /// lowercase extension, or if the file could be compiled from related
  376. /// source code.
  377. pub(crate) fn get_file_type(file: &File<'_>) -> Option<FileType> {
  378. // Case-insensitive readme is checked first for backwards compatibility.
  379. if file.name.to_lowercase().starts_with("readme") {
  380. return Some(Self::Build);
  381. }
  382. if let Some(file_type) = FILENAME_TYPES.get(&file.name) {
  383. return Some(file_type.clone());
  384. }
  385. if let Some(file_type) = file.ext.as_ref().and_then(|ext| EXTENSION_TYPES.get(ext)) {
  386. return Some(file_type.clone());
  387. }
  388. if file.name.ends_with('~') || (file.name.starts_with('#') && file.name.ends_with('#')) {
  389. return Some(Self::Temp);
  390. }
  391. if let Some(dir) = file.parent_dir {
  392. if file
  393. .get_source_files()
  394. .iter()
  395. .any(|path| dir.contains(path))
  396. {
  397. return Some(Self::Compiled);
  398. }
  399. }
  400. None
  401. }
  402. }