filetype.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. }
  26. /// Mapping from full filenames to file type.
  27. const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
  28. /* Immediate file - kick off the build of a project */
  29. "Brewfile" => FileType::Build,
  30. "bsconfig.json" => FileType::Build,
  31. "BUILD" => FileType::Build,
  32. "BUILD.bazel" => FileType::Build,
  33. "build.gradle" => FileType::Build,
  34. "build.sbt" => FileType::Build,
  35. "build.xml" => FileType::Build,
  36. "Cargo.toml" => FileType::Build,
  37. "CMakeLists.txt" => FileType::Build,
  38. "composer.json" => FileType::Build,
  39. "configure" => FileType::Build,
  40. "Containerfile" => FileType::Build,
  41. "Dockerfile" => FileType::Build,
  42. "Earthfile" => FileType::Build,
  43. "flake.nix" => FileType::Build,
  44. "Gemfile" => FileType::Build,
  45. "GNUmakefile" => FileType::Build,
  46. "Gruntfile.coffee" => FileType::Build,
  47. "Gruntfile.js" => FileType::Build,
  48. "jsconfig.json" => FileType::Build,
  49. "Justfile" => FileType::Build,
  50. "justfile" => FileType::Build,
  51. "Makefile" => FileType::Build,
  52. "makefile" => FileType::Build,
  53. "meson.build" => FileType::Build,
  54. "mix.exs" => FileType::Build,
  55. "package.json" => FileType::Build,
  56. "Pipfile" => FileType::Build,
  57. "PKGBUILD" => FileType::Build,
  58. "Podfile" => FileType::Build,
  59. "pom.xml" => FileType::Build,
  60. "Procfile" => FileType::Build,
  61. "pyproject.toml" => FileType::Build,
  62. "Rakefile" => FileType::Build,
  63. "RoboFile.php" => FileType::Build,
  64. "SConstruct" => FileType::Build,
  65. "tsconfig.json" => FileType::Build,
  66. "Vagrantfile" => FileType::Build,
  67. "webpack.config.cjs" => FileType::Build,
  68. "webpack.config.js" => FileType::Build,
  69. "WORKSPACE" => FileType::Build,
  70. /* Cryptology files */
  71. "id_dsa" => FileType::Crypto,
  72. "id_ecdsa" => FileType::Crypto,
  73. "id_ecdsa_sk" => FileType::Crypto,
  74. "id_ed25519" => FileType::Crypto,
  75. "id_ed25519_sk" => FileType::Crypto,
  76. "id_rsa" => FileType::Crypto,
  77. };
  78. /// Mapping from lowercase file extension to file type. If an image, video, music, or lossless
  79. /// extension is added also update the extension icon map.
  80. const EXTENSION_TYPES: Map<&'static str, FileType> = phf_map! {
  81. /* Immediate file - kick off the build of a project */
  82. "ninja" => FileType::Build,
  83. /* Image files */
  84. "arw" => FileType::Image,
  85. "avif" => FileType::Image,
  86. "bmp" => FileType::Image,
  87. "cbr" => FileType::Image,
  88. "cbz" => FileType::Image,
  89. "cr2" => FileType::Image,
  90. "dvi" => FileType::Image,
  91. "eps" => FileType::Image,
  92. "gif" => FileType::Image,
  93. "heic" => FileType::Image,
  94. "heif" => FileType::Image,
  95. "ico" => FileType::Image,
  96. "j2c" => FileType::Image,
  97. "j2k" => FileType::Image,
  98. "jfi" => FileType::Image,
  99. "jfif" => FileType::Image,
  100. "jif" => FileType::Image,
  101. "jp2" => FileType::Image,
  102. "jpe" => FileType::Image,
  103. "jpeg" => FileType::Image,
  104. "jpf" => FileType::Image,
  105. "jpg" => FileType::Image,
  106. "jpx" => FileType::Image,
  107. "jxl" => FileType::Image,
  108. "nef" => FileType::Image,
  109. "orf" => FileType::Image,
  110. "pbm" => FileType::Image,
  111. "pgm" => FileType::Image,
  112. "png" => FileType::Image,
  113. "pnm" => FileType::Image,
  114. "ppm" => FileType::Image,
  115. "ps" => FileType::Image,
  116. "psd" => FileType::Image,
  117. "pxm" => FileType::Image,
  118. "raw" => FileType::Image,
  119. "stl" => FileType::Image,
  120. "svg" => FileType::Image,
  121. "tif" => FileType::Image,
  122. "tiff" => FileType::Image,
  123. "webp" => FileType::Image,
  124. "xcf" => FileType::Image,
  125. "xpm" => FileType::Image,
  126. /* Video files */
  127. "avi" => FileType::Video,
  128. "flv" => FileType::Video,
  129. "heics" => FileType::Video,
  130. "m2ts" => FileType::Video,
  131. "m2v" => FileType::Video,
  132. "m4v" => FileType::Video,
  133. "mkv" => FileType::Video,
  134. "mov" => FileType::Video,
  135. "mp4" => FileType::Video,
  136. "mpeg" => FileType::Video,
  137. "mpg" => FileType::Video,
  138. "ogm" => FileType::Video,
  139. "ogv" => FileType::Video,
  140. "video" => FileType::Video,
  141. "vob" => FileType::Video,
  142. "webm" => FileType::Video,
  143. "wmv" => FileType::Video,
  144. /* Music files */
  145. "aac" => FileType::Music,
  146. "m4a" => FileType::Music,
  147. "mka" => FileType::Music,
  148. "mp2" => FileType::Music,
  149. "mp3" => FileType::Music,
  150. "ogg" => FileType::Music,
  151. "opus" => FileType::Music,
  152. "wma" => FileType::Music,
  153. /* Lossless music, rather than any other kind of data... */
  154. "alac" => FileType::Lossless,
  155. "ape" => FileType::Lossless,
  156. "flac" => FileType::Lossless,
  157. "wav" => FileType::Lossless,
  158. /* Cryptology files */
  159. "asc" => FileType::Crypto, // GnuPG ASCII armored file
  160. "gpg" => FileType::Crypto, // GnuPG encrypted file
  161. "kbx" => FileType::Crypto, // GnuPG keybox
  162. "md5" => FileType::Crypto, // MD5 checksum
  163. "p12" => FileType::Crypto, // PKCS#12 certificate (Netscape)
  164. "pem" => FileType::Crypto, // Privacy enhanced mail certificate
  165. "pfx" => FileType::Crypto, // PKCS#12 certificate (Microsoft)
  166. "pgp" => FileType::Crypto, // PGP security key
  167. "pub" => FileType::Crypto, // Public key
  168. "sha1" => FileType::Crypto, // SHA-1 hash
  169. "sha224" => FileType::Crypto, // SHA-224 hash
  170. "sha256" => FileType::Crypto, // SHA-256 hash
  171. "sha384" => FileType::Crypto, // SHA-384 hash
  172. "sha512" => FileType::Crypto, // SHA-512 hash
  173. "sig" => FileType::Crypto, // GnuPG signed file
  174. "signature" => FileType::Crypto, // e-Filing Digital Signature File (India)
  175. /* Document files */
  176. "djvu" => FileType::Document,
  177. "doc" => FileType::Document,
  178. "docx" => FileType::Document,
  179. "eml" => FileType::Document,
  180. "fotd" => FileType::Document,
  181. "gdoc" => FileType::Document,
  182. "key" => FileType::Document,
  183. "keynote" => FileType::Document,
  184. "numbers" => FileType::Document,
  185. "odp" => FileType::Document,
  186. "ods" => FileType::Document,
  187. "odt" => FileType::Document,
  188. "pages" => FileType::Document,
  189. "pdf" => FileType::Document,
  190. "ppt" => FileType::Document,
  191. "pptx" => FileType::Document,
  192. "rtf" => FileType::Document,
  193. "xls" => FileType::Document,
  194. "xlsm" => FileType::Document,
  195. "xlsx" => FileType::Document,
  196. /* Compressed/archive files */
  197. "7z" => FileType::Compressed,
  198. "ar" => FileType::Compressed,
  199. "br" => FileType::Compressed,
  200. "bz" => FileType::Compressed,
  201. "bz2" => FileType::Compressed,
  202. "bz3" => FileType::Compressed,
  203. "cpio" => FileType::Compressed,
  204. "deb" => FileType::Compressed,
  205. "dmg" => FileType::Compressed,
  206. "gz" => FileType::Compressed,
  207. "iso" => FileType::Compressed,
  208. "lz" => FileType::Compressed,
  209. "lz4" => FileType::Compressed,
  210. "lzh" => FileType::Compressed,
  211. "lzma" => FileType::Compressed,
  212. "lzo" => FileType::Compressed,
  213. "phar" => FileType::Compressed,
  214. "qcow" => FileType::Compressed,
  215. "qcow2" => FileType::Compressed,
  216. "rar" => FileType::Compressed,
  217. "rpm" => FileType::Compressed,
  218. "tar" => FileType::Compressed,
  219. "taz" => FileType::Compressed,
  220. "tbz" => FileType::Compressed,
  221. "tbz2" => FileType::Compressed,
  222. "tc" => FileType::Compressed,
  223. "tgz" => FileType::Compressed,
  224. "tlz" => FileType::Compressed,
  225. "txz" => FileType::Compressed,
  226. "tz" => FileType::Compressed,
  227. "xz" => FileType::Compressed,
  228. "vdi" => FileType::Compressed,
  229. "vhd" => FileType::Compressed,
  230. "vmdk" => FileType::Compressed,
  231. "z" => FileType::Compressed,
  232. "zip" => FileType::Compressed,
  233. "zst" => FileType::Compressed,
  234. /* Temporary files */
  235. "bak" => FileType::Temp,
  236. "bk" => FileType::Temp,
  237. "bkp" => FileType::Temp,
  238. "download" => FileType::Temp,
  239. "swn" => FileType::Temp,
  240. "swo" => FileType::Temp,
  241. "swp" => FileType::Temp,
  242. "tmp" => FileType::Temp,
  243. /* Compiler output files */
  244. "a" => FileType::Compiled, // Unix static library
  245. "bundle" => FileType::Compiled, // Mac OS X application bundle
  246. "class" => FileType::Compiled, // Java class file
  247. "dll" => FileType::Compiled, // Windows dynamic link library
  248. "dylib" => FileType::Compiled, // Mach-O dynamic library
  249. "elc" => FileType::Compiled, // Emacs compiled lisp
  250. "ko" => FileType::Compiled, // Linux kernel module
  251. "lib" => FileType::Compiled, // Windows static library
  252. "o" => FileType::Compiled, // Compiled object file
  253. "obj" => FileType::Compiled, // Compiled object file
  254. "pyc" => FileType::Compiled, // Python compiled code
  255. "pyd" => FileType::Compiled, // Python dynamic module
  256. "pyo" => FileType::Compiled, // Python optimized code
  257. "so" => FileType::Compiled, // Unix shared library
  258. "zwc" => FileType::Compiled, // zsh compiled file
  259. };
  260. impl FileType {
  261. /// Lookup the file type based on the file's name, by the file name
  262. /// lowercase extension, or if the file could be compiled from related
  263. /// source code.
  264. pub(crate) fn get_file_type(file: &File<'_>) -> Option<FileType> {
  265. // Case-insensitive readme is checked first for backwards compatibility.
  266. if file.name.to_lowercase().starts_with("readme") {
  267. return Some(Self::Build)
  268. }
  269. if let Some(file_type) = FILENAME_TYPES.get(&file.name) {
  270. return Some(file_type.clone())
  271. }
  272. if let Some(file_type) = file.ext.as_ref().and_then(|ext| EXTENSION_TYPES.get(ext)) {
  273. return Some(file_type.clone())
  274. }
  275. if file.name.ends_with('~') || (file.name.starts_with('#') && file.name.ends_with('#')) {
  276. return Some(Self::Temp)
  277. }
  278. if let Some(dir) = file.parent_dir {
  279. if file.get_source_files().iter().any(|path| dir.contains(path)) {
  280. return Some(Self::Compiled)
  281. }
  282. }
  283. None
  284. }
  285. }