Skip to main content

provenant/parsers/
mod.rs

1mod about;
2#[cfg(all(test, feature = "golden-tests"))]
3mod about_golden_test;
4#[cfg(test)]
5mod about_test;
6mod alpine;
7#[cfg(all(test, feature = "golden-tests"))]
8mod alpine_golden_test;
9mod arch;
10#[cfg(all(test, feature = "golden-tests"))]
11mod arch_golden_test;
12#[cfg(test)]
13mod arch_test;
14mod autotools;
15#[cfg(test)]
16mod autotools_test;
17mod bazel;
18#[cfg(all(test, feature = "golden-tests"))]
19mod bazel_module_golden_test;
20#[cfg(test)]
21mod bazel_module_test;
22#[cfg(test)]
23mod bazel_test;
24mod bower;
25#[cfg(test)]
26mod bower_test;
27mod buck;
28#[cfg(test)]
29mod buck_test;
30mod bun_lock;
31#[cfg(all(test, feature = "golden-tests"))]
32mod bun_lock_golden_test;
33#[cfg(test)]
34mod bun_lock_test;
35mod bun_lockb;
36#[cfg(all(test, feature = "golden-tests"))]
37mod bun_lockb_golden_test;
38#[cfg(test)]
39mod bun_lockb_test;
40mod cargo;
41#[cfg(all(test, feature = "golden-tests"))]
42mod cargo_golden_test;
43mod cargo_lock;
44#[cfg(test)]
45mod cargo_lock_test;
46#[cfg(test)]
47mod cargo_test;
48mod chef;
49#[cfg(test)]
50mod chef_test;
51mod clojure;
52#[cfg(all(test, feature = "golden-tests"))]
53mod clojure_golden_test;
54#[cfg(test)]
55mod clojure_test;
56#[cfg(all(test, feature = "golden-tests"))]
57mod cocoapods_golden_test;
58mod composer;
59#[cfg(all(test, feature = "golden-tests"))]
60mod composer_golden_test;
61#[cfg(test)]
62mod composer_test;
63mod conan;
64mod conan_data;
65#[cfg(test)]
66mod conan_data_test;
67#[cfg(all(test, feature = "golden-tests"))]
68mod conan_golden_test;
69#[cfg(test)]
70mod conan_test;
71mod conda;
72#[cfg(all(test, feature = "golden-tests"))]
73mod conda_golden_test;
74mod conda_meta_json;
75#[cfg(test)]
76mod conda_meta_json_test;
77#[cfg(test)]
78mod conda_test;
79mod cpan;
80mod cpan_dist_ini;
81#[cfg(test)]
82mod cpan_dist_ini_test;
83mod cpan_makefile_pl;
84#[cfg(test)]
85mod cpan_makefile_pl_test;
86#[cfg(test)]
87mod cpan_test;
88mod cran;
89#[cfg(all(test, feature = "golden-tests"))]
90mod cran_golden_test;
91#[cfg(test)]
92mod cran_test;
93mod dart;
94#[cfg(all(test, feature = "golden-tests"))]
95mod dart_golden_test;
96#[cfg(test)]
97mod dart_test;
98mod debian;
99#[cfg(all(test, feature = "golden-tests"))]
100mod debian_golden_test;
101#[cfg(test)]
102mod debian_test;
103mod deno;
104#[cfg(all(test, feature = "golden-tests"))]
105mod deno_golden_test;
106mod deno_lock;
107#[cfg(test)]
108mod deno_lock_test;
109#[cfg(test)]
110mod deno_test;
111mod docker;
112#[cfg(all(test, feature = "golden-tests"))]
113mod docker_golden_test;
114#[cfg(test)]
115mod docker_test;
116mod freebsd;
117#[cfg(test)]
118mod freebsd_test;
119mod gitmodules;
120mod go;
121#[cfg(all(test, feature = "golden-tests"))]
122mod go_golden_test;
123mod go_mod_graph;
124#[cfg(test)]
125mod go_test;
126#[cfg(test)]
127mod go_work_test;
128mod gradle;
129#[cfg(all(test, feature = "golden-tests"))]
130mod gradle_golden_test;
131mod gradle_lock;
132#[cfg(test)]
133mod gradle_lock_test;
134mod gradle_module;
135#[cfg(all(test, feature = "golden-tests"))]
136mod gradle_module_golden_test;
137#[cfg(test)]
138mod gradle_module_test;
139mod hackage;
140#[cfg(all(test, feature = "golden-tests"))]
141mod hackage_golden_test;
142#[cfg(test)]
143mod hackage_test;
144mod haxe;
145#[cfg(all(test, feature = "golden-tests"))]
146mod haxe_golden_test;
147#[cfg(test)]
148mod haxe_test;
149mod helm;
150#[cfg(all(test, feature = "golden-tests"))]
151mod helm_golden_test;
152#[cfg(test)]
153mod helm_test;
154mod hex_lock;
155#[cfg(all(test, feature = "golden-tests"))]
156mod hex_lock_golden_test;
157#[cfg(test)]
158mod hex_lock_test;
159mod maven;
160#[cfg(all(test, feature = "golden-tests"))]
161mod maven_golden_test;
162#[cfg(test)]
163mod maven_test;
164mod meson;
165#[cfg(all(test, feature = "golden-tests"))]
166mod meson_golden_test;
167#[cfg(test)]
168mod meson_test;
169pub mod metadata;
170mod microsoft_update_manifest;
171#[cfg(test)]
172mod microsoft_update_manifest_test;
173mod misc;
174#[cfg(test)]
175mod misc_test;
176mod npm;
177#[cfg(all(test, feature = "golden-tests"))]
178mod npm_golden_test;
179mod npm_lock;
180#[cfg(test)]
181mod npm_lock_test;
182#[cfg(test)]
183mod npm_test;
184mod npm_workspace;
185#[cfg(test)]
186mod npm_workspace_test;
187mod nuget;
188#[cfg(all(test, feature = "golden-tests"))]
189mod nuget_golden_test;
190#[cfg(test)]
191mod nuget_test;
192mod opam;
193#[cfg(all(test, feature = "golden-tests"))]
194mod opam_golden_test;
195mod os_release;
196#[cfg(test)]
197mod os_release_test;
198#[cfg(test)]
199mod osgi_test;
200mod pep508;
201mod pip_inspect_deplock;
202#[cfg(test)]
203mod pip_inspect_deplock_test;
204mod pipfile_lock;
205#[cfg(all(test, feature = "golden-tests"))]
206mod pipfile_lock_golden_test;
207#[cfg(test)]
208mod pipfile_lock_test;
209mod pixi;
210#[cfg(all(test, feature = "golden-tests"))]
211mod pixi_golden_test;
212#[cfg(test)]
213mod pixi_test;
214mod pnpm_lock;
215#[cfg(test)]
216mod pnpm_lock_test;
217mod podfile;
218mod podfile_lock;
219#[cfg(test)]
220mod podfile_lock_test;
221mod podspec;
222mod podspec_json;
223#[cfg(test)]
224mod podspec_json_test;
225mod poetry_lock;
226#[cfg(all(test, feature = "golden-tests"))]
227mod poetry_lock_golden_test;
228#[cfg(test)]
229mod poetry_lock_test;
230mod pylock_toml;
231#[cfg(all(test, feature = "golden-tests"))]
232mod pylock_toml_golden_test;
233#[cfg(test)]
234mod pylock_toml_test;
235mod python;
236#[cfg(all(test, feature = "golden-tests"))]
237mod python_golden_test;
238#[cfg(test)]
239mod python_test;
240mod readme;
241#[cfg(all(test, feature = "golden-tests"))]
242mod readme_golden_test;
243#[cfg(test)]
244mod readme_test;
245mod requirements_txt;
246#[cfg(all(test, feature = "golden-tests"))]
247mod requirements_txt_golden_test;
248#[cfg(test)]
249mod requirements_txt_test;
250pub(crate) mod rfc822;
251mod rpm_db;
252#[cfg(all(test, feature = "golden-tests"))]
253mod rpm_golden_test;
254mod rpm_license_files;
255#[cfg(test)]
256mod rpm_license_files_test;
257mod rpm_mariner_manifest;
258#[cfg(test)]
259mod rpm_mariner_manifest_test;
260mod rpm_parser;
261mod rpm_specfile;
262#[cfg(test)]
263mod rpm_specfile_test;
264mod rpm_yumdb;
265mod ruby;
266#[cfg(all(test, feature = "golden-tests"))]
267mod ruby_golden_test;
268#[cfg(test)]
269mod ruby_test;
270mod sbt;
271#[cfg(all(test, feature = "golden-tests"))]
272mod sbt_golden_test;
273#[cfg(test)]
274mod sbt_test;
275#[cfg(all(test, feature = "golden-tests"))]
276mod swift_golden_test;
277mod swift_manifest_json;
278#[cfg(test)]
279mod swift_manifest_json_test;
280mod swift_resolved;
281#[cfg(test)]
282mod swift_resolved_test;
283mod swift_show_dependencies;
284#[cfg(test)]
285mod swift_show_dependencies_test;
286pub mod utils;
287mod uv_lock;
288#[cfg(all(test, feature = "golden-tests"))]
289mod uv_lock_golden_test;
290#[cfg(test)]
291mod uv_lock_test;
292mod vcpkg;
293#[cfg(all(test, feature = "golden-tests"))]
294mod vcpkg_golden_test;
295#[cfg(test)]
296mod vcpkg_test;
297mod yarn_lock;
298#[cfg(test)]
299mod yarn_lock_test;
300
301use std::path::Path;
302
303use crate::models::{PackageData, PackageType};
304
305/// Package parser trait for extracting metadata from package manifest files.
306///
307/// Each parser implementation handles a specific package manager/ecosystem
308/// (npm, Maven, Python, Cargo, etc.) and extracts standardized metadata into
309/// `PackageData` structures compatible with ScanCode Toolkit JSON output format.
310///
311/// # Implementation Guide
312///
313/// Implementors must provide:
314/// - `PACKAGE_TYPE`: Package URL (purl) type identifier (e.g., "npm", "pypi", "maven")
315/// - `is_match()`: Returns true if the given file path matches this parser's expected format
316/// - `extract_packages()`: Parses the file and returns all extracted package metadata
317///
318/// # Error Handling
319///
320/// Parsers should handle errors gracefully by returning default/empty `PackageData`
321/// and logging warnings rather than panicking. This allows the scan to continue
322/// processing other files even when individual files fail to parse.
323///
324/// # Example
325///
326/// ```ignore
327/// use provenant::models::{PackageData, PackageType};
328/// use provenant::parsers::PackageParser;
329/// use std::path::Path;
330///
331/// pub struct MyParser;
332///
333/// impl PackageParser for MyParser {
334///     const PACKAGE_TYPE: PackageType = PackageType::Npm;
335///
336///     fn is_match(path: &Path) -> bool {
337///         path.file_name().is_some_and(|name| name == "package.json")
338///     }
339///
340///     fn extract_packages(path: &Path) -> Vec<PackageData> {
341///         // Parse file and return metadata
342///         // On error, log warning and return default
343///         vec![PackageData::default()]
344///     }
345/// }
346/// ```
347pub trait PackageParser {
348    /// Package URL type identifier for this parser (e.g., PackageType::Npm, PackageType::Pypi).
349    const PACKAGE_TYPE: PackageType;
350
351    /// Extracts all packages from the given file path.
352    ///
353    /// Returns a vector of `PackageData` structures containing all extracted metadata
354    /// including name, version, dependencies, licenses, etc. Most parsers return a
355    /// single-element vector, but some (e.g., Bazel BUILD, Buck BUCK, Debian control)
356    /// can contain multiple packages in a single file.
357    ///
358    /// On parse errors, returns a vector with a default `PackageData` with minimal or
359    /// no fields populated.
360    fn extract_packages(path: &Path) -> Vec<PackageData>;
361
362    /// Checks if the given file path matches this parser's expected format.
363    ///
364    /// Returns true if the file should be handled by this parser based on filename,
365    /// extension, or path patterns. Used by the scanner to route files to appropriate parsers.
366    fn is_match(path: &Path) -> bool;
367
368    /// Returns the first package from [`extract_packages()`](Self::extract_packages),
369    /// or a default [`PackageData`] if the file contains no packages.
370    fn extract_first_package(path: &Path) -> PackageData {
371        Self::extract_packages(path)
372            .into_iter()
373            .next()
374            .unwrap_or_default()
375    }
376}
377
378pub use self::about::AboutFileParser;
379pub use self::alpine::{AlpineApkParser, AlpineApkbuildParser, AlpineInstalledParser};
380pub use self::arch::{ArchPkginfoParser, ArchSrcinfoParser};
381pub use self::autotools::AutotoolsConfigureParser;
382pub use self::bazel::{BazelBuildParser, BazelModuleParser};
383pub use self::bower::BowerJsonParser;
384pub use self::buck::{BuckBuildParser, BuckMetadataBzlParser};
385pub use self::bun_lock::BunLockParser;
386pub use self::bun_lockb::BunLockbParser;
387pub use self::cargo::CargoParser;
388#[cfg_attr(not(test), allow(unused_imports))]
389pub use self::cargo_lock::CargoLockParser;
390pub use self::chef::{ChefMetadataJsonParser, ChefMetadataRbParser};
391pub use self::clojure::{ClojureDepsEdnParser, ClojureProjectCljParser};
392pub use self::composer::{ComposerJsonParser, ComposerLockParser};
393pub use self::conan::{ConanFilePyParser, ConanLockParser, ConanfileTxtParser};
394pub use self::conan_data::ConanDataParser;
395pub use self::conda::{CondaEnvironmentYmlParser, CondaMetaYamlParser};
396pub use self::conda_meta_json::CondaMetaJsonParser;
397pub use self::cpan::{CpanManifestParser, CpanMetaJsonParser, CpanMetaYmlParser};
398pub use self::cpan_dist_ini::CpanDistIniParser;
399pub use self::cpan_makefile_pl::CpanMakefilePlParser;
400pub use self::cran::CranParser;
401pub use self::dart::{PubspecLockParser, PubspecYamlParser};
402pub use self::debian::{
403    DebianControlInExtractedDebParser, DebianControlParser, DebianCopyrightParser, DebianDebParser,
404    DebianDebianTarParser, DebianDistrolessInstalledParser, DebianDscParser,
405    DebianInstalledListParser, DebianInstalledMd5sumsParser, DebianInstalledParser,
406    DebianMd5sumInPackageParser, DebianOrigTarParser,
407};
408pub use self::deno::DenoParser;
409pub use self::deno_lock::DenoLockParser;
410pub use self::docker::DockerfileParser;
411pub use self::freebsd::FreebsdCompactManifestParser;
412pub use self::gitmodules::GitmodulesParser;
413pub use self::go::{GoModParser, GoSumParser, GoWorkParser, GodepsParser};
414pub use self::go_mod_graph::GoModGraphParser;
415pub use self::gradle::GradleParser;
416pub use self::gradle_lock::GradleLockfileParser;
417pub use self::gradle_module::GradleModuleParser;
418pub use self::hackage::{HackageCabalParser, HackageCabalProjectParser, HackageStackYamlParser};
419pub use self::haxe::HaxeParser;
420pub use self::helm::{HelmChartLockParser, HelmChartYamlParser};
421pub use self::hex_lock::HexLockParser;
422pub use self::maven::MavenParser;
423pub use self::meson::MesonParser;
424pub use self::microsoft_update_manifest::MicrosoftUpdateManifestParser;
425pub use self::misc::{
426    AndroidApkRecognizer, AndroidLibraryRecognizer, AppleDmgRecognizer, Axis2MarRecognizer,
427    Axis2ModuleXmlRecognizer, CabArchiveRecognizer, ChromeCrxRecognizer, InstallShieldRecognizer,
428    IosIpaRecognizer, IsoImageRecognizer, IvyXmlRecognizer, JBossSarRecognizer,
429    JBossServiceXmlRecognizer, JavaEarAppXmlRecognizer, JavaEarRecognizer, JavaJarRecognizer,
430    JavaWarRecognizer, JavaWarWebXmlRecognizer, MeteorPackageRecognizer, MozillaXpiRecognizer,
431    NsisRecognizer, SharArchiveRecognizer, SquashfsRecognizer,
432};
433pub use self::npm::NpmParser;
434pub use self::npm_lock::NpmLockParser;
435pub use self::npm_workspace::NpmWorkspaceParser;
436pub use self::nuget::{
437    CentralPackageManagementPropsParser, DirectoryBuildPropsParser, DotNetDepsJsonParser,
438    NupkgParser, NuspecParser, PackageReferenceProjectParser, PackagesConfigParser,
439    PackagesLockParser, ProjectJsonParser, ProjectLockJsonParser,
440};
441pub use self::opam::OpamParser;
442pub use self::os_release::OsReleaseParser;
443pub use self::pip_inspect_deplock::PipInspectDeplockParser;
444pub use self::pipfile_lock::PipfileLockParser;
445pub use self::pixi::{PixiLockParser, PixiTomlParser};
446pub use self::pnpm_lock::PnpmLockParser;
447pub use self::podfile::PodfileParser;
448pub use self::podfile_lock::PodfileLockParser;
449pub use self::podspec::PodspecParser;
450pub use self::podspec_json::PodspecJsonParser;
451pub use self::poetry_lock::PoetryLockParser;
452pub use self::pylock_toml::PylockTomlParser;
453pub use self::python::PythonParser;
454pub use self::readme::ReadmeParser;
455pub use self::requirements_txt::RequirementsTxtParser;
456pub use self::rpm_db::{RpmBdbDatabaseParser, RpmNdbDatabaseParser, RpmSqliteDatabaseParser};
457pub use self::rpm_license_files::RpmLicenseFilesParser;
458pub use self::rpm_mariner_manifest::RpmMarinerManifestParser;
459pub use self::rpm_parser::RpmParser;
460pub use self::rpm_specfile::RpmSpecfileParser;
461pub use self::rpm_yumdb::RpmYumdbParser;
462pub use self::ruby::{
463    GemArchiveParser, GemMetadataExtractedParser, GemfileLockParser, GemfileParser, GemspecParser,
464};
465pub use self::sbt::SbtParser;
466pub use self::swift_manifest_json::SwiftManifestJsonParser;
467pub use self::swift_resolved::SwiftPackageResolvedParser;
468pub use self::swift_show_dependencies::SwiftShowDependenciesParser;
469pub use self::uv_lock::UvLockParser;
470pub use self::vcpkg::VcpkgManifestParser;
471pub use self::yarn_lock::YarnLockParser;
472
473/// Registers all parsers and recognizers, generating dispatch functions.
474///
475/// Parsers are tried first, then recognizers. This ordering is important because
476/// recognizers match broadly by file extension (e.g., `.jar`) and would shadow
477/// more specific parsers if checked first.
478macro_rules! register_package_handlers {
479    (
480        parsers: [$($parser:ty),* $(,)?],
481        recognizers: [$($recognizer:ty),* $(,)?] $(,)?
482    ) => {
483        pub fn try_parse_file(path: &Path) -> Option<Vec<PackageData>> {
484            $(
485                if <$parser>::is_match(path) {
486                    return Some(<$parser>::extract_packages(path));
487                }
488            )*
489            $(
490                if <$recognizer>::is_match(path) {
491                    return Some(<$recognizer>::extract_packages(path));
492                }
493            )*
494            None
495        }
496
497        // Used by the parser-golden maintenance tool in `xtask`.
498        // Scanner runtime dispatch goes through `try_parse_file()` instead.
499        #[allow(dead_code)]
500        pub fn parse_by_type_name(type_name: &str, path: &Path) -> Option<PackageData> {
501            match type_name {
502                $(
503                    stringify!($parser) => Some(<$parser>::extract_first_package(path)),
504                )*
505                $(
506                    stringify!($recognizer) => Some(<$recognizer>::extract_first_package(path)),
507                )*
508                _ => None
509            }
510        }
511
512        // Used by the parser-golden maintenance tool in `xtask` and by
513        // `tests/scanner_integration.rs` to verify parser registration.
514        #[allow(dead_code)]
515        pub fn list_parser_types() -> Vec<&'static str> {
516            vec![
517                $(
518                    stringify!($parser),
519                )*
520                $(
521                    stringify!($recognizer),
522                )*
523            ]
524        }
525    };
526}
527
528register_package_handlers! {
529    parsers: [
530        AboutFileParser,
531        AlpineApkParser,
532        AlpineApkbuildParser,
533        AlpineInstalledParser,
534        ArchPkginfoParser,
535        ArchSrcinfoParser,
536        AutotoolsConfigureParser,
537        BazelBuildParser,
538        BazelModuleParser,
539        BowerJsonParser,
540        BunLockParser,
541        BunLockbParser,
542        BuckBuildParser,
543        BuckMetadataBzlParser,
544        CargoLockParser,
545        CargoParser,
546        ChefMetadataJsonParser,
547        ChefMetadataRbParser,
548        ClojureDepsEdnParser,
549        ClojureProjectCljParser,
550        ComposerJsonParser,
551        ComposerLockParser,
552        ConanDataParser,
553        ConanFilePyParser,
554        ConanfileTxtParser,
555        ConanLockParser,
556        CondaEnvironmentYmlParser,
557        CondaMetaJsonParser,
558        CondaMetaYamlParser,
559        CpanDistIniParser,
560        CpanMakefilePlParser,
561        CpanManifestParser,
562        CpanMetaJsonParser,
563        CpanMetaYmlParser,
564        CranParser,
565        DebianControlInExtractedDebParser,
566        DebianControlParser,
567        DebianCopyrightParser,
568        DebianDebianTarParser,
569        DebianDebParser,
570        DebianDistrolessInstalledParser,
571        DebianDscParser,
572        DebianInstalledListParser,
573        DebianInstalledMd5sumsParser,
574        DebianInstalledParser,
575        DebianMd5sumInPackageParser,
576        DebianOrigTarParser,
577        DenoParser,
578        DenoLockParser,
579        DockerfileParser,
580        FreebsdCompactManifestParser,
581        GemArchiveParser,
582        GemfileLockParser,
583        GemfileParser,
584        GemMetadataExtractedParser,
585        GemspecParser,
586        GitmodulesParser,
587        GodepsParser,
588        GoModParser,
589        GoModGraphParser,
590        GoSumParser,
591        GoWorkParser,
592        GradleLockfileParser,
593        GradleParser,
594        GradleModuleParser,
595        HackageCabalParser,
596        HackageCabalProjectParser,
597        HackageStackYamlParser,
598        HelmChartYamlParser,
599        HelmChartLockParser,
600        HaxeParser,
601        HexLockParser,
602        MavenParser,
603        MesonParser,
604        MicrosoftUpdateManifestParser,
605        NpmLockParser,
606        NpmParser,
607        NpmWorkspaceParser,
608        DotNetDepsJsonParser,
609        CentralPackageManagementPropsParser,
610        DirectoryBuildPropsParser,
611        NupkgParser,
612        NuspecParser,
613        PackageReferenceProjectParser,
614        OpamParser,
615        OsReleaseParser,
616        PackagesConfigParser,
617        PackagesLockParser,
618        ProjectJsonParser,
619        ProjectLockJsonParser,
620        PipfileLockParser,
621        PipInspectDeplockParser,
622        PixiTomlParser,
623        PixiLockParser,
624        PnpmLockParser,
625        PodfileLockParser,
626        PodfileParser,
627        PodspecJsonParser,
628        PodspecParser,
629        PoetryLockParser,
630        PylockTomlParser,
631        PubspecLockParser,
632        PubspecYamlParser,
633        PythonParser,
634        UvLockParser,
635        VcpkgManifestParser,
636        ReadmeParser,
637        RequirementsTxtParser,
638        RpmBdbDatabaseParser,
639        RpmLicenseFilesParser,
640        RpmMarinerManifestParser,
641        RpmNdbDatabaseParser,
642        RpmParser,
643        RpmSpecfileParser,
644        RpmSqliteDatabaseParser,
645        RpmYumdbParser,
646        SbtParser,
647        SwiftManifestJsonParser,
648        SwiftPackageResolvedParser,
649        SwiftShowDependenciesParser,
650        YarnLockParser,
651    ],
652    recognizers: [
653        AndroidApkRecognizer,
654        AndroidLibraryRecognizer,
655        AppleDmgRecognizer,
656        Axis2MarRecognizer,
657        Axis2ModuleXmlRecognizer,
658        CabArchiveRecognizer,
659        ChromeCrxRecognizer,
660        InstallShieldRecognizer,
661        IosIpaRecognizer,
662        IsoImageRecognizer,
663        IvyXmlRecognizer,
664        JavaEarAppXmlRecognizer,
665        JavaEarRecognizer,
666        JavaJarRecognizer,
667        JavaWarRecognizer,
668        JavaWarWebXmlRecognizer,
669        JBossSarRecognizer,
670        JBossServiceXmlRecognizer,
671        MeteorPackageRecognizer,
672        MozillaXpiRecognizer,
673        NsisRecognizer,
674        SharArchiveRecognizer,
675        SquashfsRecognizer,
676    ],
677}