filetype.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. "stl" => FileType::Image,
  121. "svg" => FileType::Image,
  122. "tif" => FileType::Image,
  123. "tiff" => FileType::Image,
  124. "webp" => FileType::Image,
  125. "xcf" => FileType::Image,
  126. "xpm" => FileType::Image,
  127. /* Video files */
  128. "avi" => FileType::Video,
  129. "flv" => FileType::Video,
  130. "h264" => FileType::Video,
  131. "heics" => FileType::Video,
  132. "m2ts" => FileType::Video,
  133. "m2v" => FileType::Video,
  134. "m4v" => FileType::Video,
  135. "mkv" => FileType::Video,
  136. "mov" => FileType::Video,
  137. "mp4" => FileType::Video,
  138. "mpeg" => FileType::Video,
  139. "mpg" => FileType::Video,
  140. "ogm" => FileType::Video,
  141. "ogv" => FileType::Video,
  142. "video" => FileType::Video,
  143. "vob" => FileType::Video,
  144. "webm" => FileType::Video,
  145. "wmv" => FileType::Video,
  146. /* Music files */
  147. "aac" => FileType::Music,
  148. "m4a" => FileType::Music,
  149. "mka" => FileType::Music,
  150. "mp2" => FileType::Music,
  151. "mp3" => FileType::Music,
  152. "ogg" => FileType::Music,
  153. "opus" => FileType::Music,
  154. "wma" => FileType::Music,
  155. /* Lossless music, rather than any other kind of data... */
  156. "aif" => FileType::Lossless,
  157. "aifc" => FileType::Lossless,
  158. "aiff" => FileType::Lossless,
  159. "alac" => FileType::Lossless,
  160. "ape" => FileType::Lossless,
  161. "flac" => FileType::Lossless,
  162. "pcm" => FileType::Lossless,
  163. "wav" => FileType::Lossless,
  164. "wv" => FileType::Lossless,
  165. /* Cryptology files */
  166. "asc" => FileType::Crypto, // GnuPG ASCII armored file
  167. "gpg" => FileType::Crypto, // GnuPG encrypted file
  168. "kbx" => FileType::Crypto, // GnuPG keybox
  169. "md5" => FileType::Crypto, // MD5 checksum
  170. "p12" => FileType::Crypto, // PKCS#12 certificate (Netscape)
  171. "pem" => FileType::Crypto, // Privacy enhanced mail certificate
  172. "pfx" => FileType::Crypto, // PKCS#12 certificate (Microsoft)
  173. "pgp" => FileType::Crypto, // PGP security key
  174. "pub" => FileType::Crypto, // Public key
  175. "sha1" => FileType::Crypto, // SHA-1 hash
  176. "sha224" => FileType::Crypto, // SHA-224 hash
  177. "sha256" => FileType::Crypto, // SHA-256 hash
  178. "sha384" => FileType::Crypto, // SHA-384 hash
  179. "sha512" => FileType::Crypto, // SHA-512 hash
  180. "sig" => FileType::Crypto, // GnuPG signed file
  181. "signature" => FileType::Crypto, // e-Filing Digital Signature File (India)
  182. /* Document files */
  183. "djvu" => FileType::Document,
  184. "doc" => FileType::Document,
  185. "docx" => FileType::Document,
  186. "eml" => FileType::Document,
  187. "fotd" => FileType::Document,
  188. "gdoc" => FileType::Document,
  189. "key" => FileType::Document,
  190. "keynote" => FileType::Document,
  191. "numbers" => FileType::Document,
  192. "odp" => FileType::Document,
  193. "ods" => FileType::Document,
  194. "odt" => FileType::Document,
  195. "pages" => FileType::Document,
  196. "pdf" => FileType::Document,
  197. "ppt" => FileType::Document,
  198. "pptx" => FileType::Document,
  199. "rtf" => FileType::Document,
  200. "xls" => FileType::Document,
  201. "xlsm" => FileType::Document,
  202. "xlsx" => FileType::Document,
  203. /* Compressed/archive files */
  204. "7z" => FileType::Compressed,
  205. "ar" => FileType::Compressed,
  206. "arj" => FileType::Compressed,
  207. "br" => FileType::Compressed,
  208. "bz" => FileType::Compressed,
  209. "bz2" => FileType::Compressed,
  210. "bz3" => FileType::Compressed,
  211. "cpio" => FileType::Compressed,
  212. "deb" => FileType::Compressed,
  213. "dmg" => FileType::Compressed,
  214. "gz" => FileType::Compressed,
  215. "iso" => FileType::Compressed,
  216. "lz" => FileType::Compressed,
  217. "lz4" => FileType::Compressed,
  218. "lzh" => FileType::Compressed,
  219. "lzma" => FileType::Compressed,
  220. "lzo" => FileType::Compressed,
  221. "phar" => FileType::Compressed,
  222. "qcow" => FileType::Compressed,
  223. "qcow2" => FileType::Compressed,
  224. "rar" => FileType::Compressed,
  225. "rpm" => FileType::Compressed,
  226. "tar" => FileType::Compressed,
  227. "taz" => FileType::Compressed,
  228. "tbz" => FileType::Compressed,
  229. "tbz2" => FileType::Compressed,
  230. "tc" => FileType::Compressed,
  231. "tgz" => FileType::Compressed,
  232. "tlz" => FileType::Compressed,
  233. "txz" => FileType::Compressed,
  234. "tz" => FileType::Compressed,
  235. "xz" => FileType::Compressed,
  236. "vdi" => FileType::Compressed,
  237. "vhd" => FileType::Compressed,
  238. "vmdk" => FileType::Compressed,
  239. "z" => FileType::Compressed,
  240. "zip" => FileType::Compressed,
  241. "zst" => FileType::Compressed,
  242. /* Temporary files */
  243. "bak" => FileType::Temp,
  244. "bk" => FileType::Temp,
  245. "bkp" => FileType::Temp,
  246. "crdownload" => FileType::Temp,
  247. "download" => FileType::Temp,
  248. "fdmdownload"=> FileType::Temp,
  249. "part" => FileType::Temp,
  250. "swn" => FileType::Temp,
  251. "swo" => FileType::Temp,
  252. "swp" => FileType::Temp,
  253. "tmp" => FileType::Temp,
  254. /* Compiler output files */
  255. "a" => FileType::Compiled, // Unix static library
  256. "bundle" => FileType::Compiled, // Mac OS X application bundle
  257. "class" => FileType::Compiled, // Java class file
  258. "cma" => FileType::Compiled, // OCaml bytecode library
  259. "cmi" => FileType::Compiled, // OCaml interface
  260. "cmo" => FileType::Compiled, // OCaml bytecode object
  261. "cmx" => FileType::Compiled, // OCaml bytecode object for inlining
  262. "dll" => FileType::Compiled, // Windows dynamic link library
  263. "dylib" => FileType::Compiled, // Mach-O dynamic library
  264. "elc" => FileType::Compiled, // Emacs compiled lisp
  265. "ko" => FileType::Compiled, // Linux kernel module
  266. "lib" => FileType::Compiled, // Windows static library
  267. "o" => FileType::Compiled, // Compiled object file
  268. "obj" => FileType::Compiled, // Compiled object file
  269. "pyc" => FileType::Compiled, // Python compiled code
  270. "pyd" => FileType::Compiled, // Python dynamic module
  271. "pyo" => FileType::Compiled, // Python optimized code
  272. "so" => FileType::Compiled, // Unix shared library
  273. "zwc" => FileType::Compiled, // zsh compiled file
  274. /* Source code */
  275. "applescript"=> FileType::Source, // Apple script
  276. "as" => FileType::Source, // Action script
  277. "asa" => FileType::Source, // asp
  278. "awk" => FileType::Source, // awk
  279. "c" => FileType::Source, // C/C++
  280. "c++" => FileType::Source, // C/C++
  281. "cabal" => FileType::Source, // Cabal
  282. "cc" => FileType::Source, // C/C++
  283. "clj" => FileType::Source, // Clojure
  284. "cp" => FileType::Source, // C/C++ Xcode
  285. "cpp" => FileType::Source, // C/C++
  286. "cr" => FileType::Source, // Crystal
  287. "cs" => FileType::Source, // C#
  288. "css" => FileType::Source, // css
  289. "csx" => FileType::Source, // C#
  290. "cu" => FileType::Source, // CUDA
  291. "cxx" => FileType::Source, // C/C++
  292. "d" => FileType::Source, // D
  293. "dart" => FileType::Source, // Dart
  294. "di" => FileType::Source, // D
  295. "dpr" => FileType::Source, // Delphi Pascal
  296. "el" => FileType::Source, // Lisp
  297. "elm" => FileType::Source, // Elm
  298. "erl" => FileType::Source, // Erlang
  299. "ex" => FileType::Source, // Elixir
  300. "exs" => FileType::Source, // Elixir
  301. "fs" => FileType::Source, // F#
  302. "fsh" => FileType::Source, // Fragment shader
  303. "fsi" => FileType::Source, // F#
  304. "fsx" => FileType::Source, // F#
  305. "go" => FileType::Source, // Go
  306. "gradle" => FileType::Source, // Gradle
  307. "groovy" => FileType::Source, // Groovy
  308. "gvy" => FileType::Source, // Groovy
  309. "h" => FileType::Source, // C/C++
  310. "h++" => FileType::Source, // C/C++
  311. "hpp" => FileType::Source, // C/C++
  312. "hs" => FileType::Source, // Haskell
  313. "htc" => FileType::Source, // Javascript
  314. "hxx" => FileType::Source, // C/C++
  315. "inc" => FileType::Source,
  316. "inl" => FileType::Source, // C/C++ Microsoft
  317. "ipynb" => FileType::Source, // Jupyter Notebook
  318. "java" => FileType::Source, // Java
  319. "jl" => FileType::Source, // Julia
  320. "js" => FileType::Source, // Javascript
  321. "jsx" => FileType::Source, // React
  322. "kt" => FileType::Source, // Kotlin
  323. "kts" => FileType::Source, // Kotlin
  324. "less" => FileType::Source, // less
  325. "lhs" => FileType::Source, // Haskell
  326. "lisp" => FileType::Source, // Lisp
  327. "ltx" => FileType::Source, // LaTeX
  328. "lua" => FileType::Source, // Lua
  329. "m" => FileType::Source, // Matlab
  330. "matlab" => FileType::Source, // Matlab
  331. "ml" => FileType::Source, // OCaml
  332. "mli" => FileType::Source, // OCaml
  333. "mn" => FileType::Source, // Matlab
  334. "nb" => FileType::Source, // Mathematica
  335. "p" => FileType::Source, // Pascal
  336. "pas" => FileType::Source, // Pascal
  337. "php" => FileType::Source, // PHP
  338. "pl" => FileType::Source, // Perl
  339. "pm" => FileType::Source, // Perl
  340. "pod" => FileType::Source, // Perl
  341. "pp" => FileType::Source, // Puppet
  342. "ps1" => FileType::Source, // PowerShell
  343. "psd1" => FileType::Source, // PowerShell
  344. "psm1" => FileType::Source, // PowerShell
  345. "purs" => FileType::Source, // PureScript
  346. "py" => FileType::Source, // Python
  347. "r" => FileType::Source, // R
  348. "rb" => FileType::Source, // Ruby
  349. "rs" => FileType::Source, // Rust
  350. "sass" => FileType::Source, // Sass
  351. "scala" => FileType::Source, // Scala
  352. "scss" => FileType::Source, // Sass
  353. "sql" => FileType::Source, // SQL
  354. "swift" => FileType::Source, // Swift
  355. "tcl" => FileType::Source, // TCL
  356. "tex" => FileType::Source, // LaTeX
  357. "ts" => FileType::Source, // TypeScript
  358. "v" => FileType::Source, // V
  359. "vb" => FileType::Source, // Visual Basic
  360. "vsh" => FileType::Source, // Vertex shader
  361. };
  362. impl FileType {
  363. /// Lookup the file type based on the file's name, by the file name
  364. /// lowercase extension, or if the file could be compiled from related
  365. /// source code.
  366. pub(crate) fn get_file_type(file: &File<'_>) -> Option<FileType> {
  367. // Case-insensitive readme is checked first for backwards compatibility.
  368. if file.name.to_lowercase().starts_with("readme") {
  369. return Some(Self::Build);
  370. }
  371. if let Some(file_type) = FILENAME_TYPES.get(&file.name) {
  372. return Some(file_type.clone());
  373. }
  374. if let Some(file_type) = file.ext.as_ref().and_then(|ext| EXTENSION_TYPES.get(ext)) {
  375. return Some(file_type.clone());
  376. }
  377. if file.name.ends_with('~') || (file.name.starts_with('#') && file.name.ends_with('#')) {
  378. return Some(Self::Temp);
  379. }
  380. if let Some(dir) = file.parent_dir {
  381. if file
  382. .get_source_files()
  383. .iter()
  384. .any(|path| dir.contains(path))
  385. {
  386. return Some(Self::Compiled);
  387. }
  388. }
  389. None
  390. }
  391. }