1use serde::{Deserialize, Serialize};
13use std::fmt;
14use std::str::FromStr;
15use strum::{EnumCount, EnumIter};
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, EnumCount, EnumIter)]
29pub enum DatasourceId {
30 AboutFile,
32 Readme,
33 EtcOsRelease,
34
35 AlpineApkArchive,
37 AlpineApkbuild,
38 AlpineInstalledDb,
39
40 ArchAurinfo,
42 ArchPkginfo,
43 ArchSrcinfo,
44
45 AndroidAab,
47 AndroidAarLibrary,
48 AndroidApk,
49 AndroidManifestXml,
50 AndroidSoongMetadata,
51
52 Axis2Mar,
54 Axis2ModuleXml,
55
56 AutotoolsConfigure,
58
59 BazelBuild,
61 BazelModule,
62
63 BitbakeRecipe,
65 BitbakeRecipeAppend,
66
67 BowerJson,
69
70 BuckFile,
72 BuckMetadata,
73
74 BunLock,
76 BunLockb,
77
78 CarthageCartfile,
80 CarthageCartfileResolved,
81
82 CargoLock,
84 CargoToml,
85 RustBinary,
86 WindowsExecutable,
87
88 ChefCookbookMetadataJson,
91 ChefCookbookMetadataRb,
93
94 CitationCff,
95
96 CocoapodsPodfile,
98 CocoapodsPodfileLock,
99 CocoapodsPodspec,
100 CocoapodsPodspecJson,
101
102 ConanConanDataYml,
104 ConanConanFilePy,
105 ConanConanFileTxt,
106 ConanLock,
107
108 CondaYaml,
111 CondaMetaJson,
112 CondaMetaYaml,
113
114 ClojureDepsEdn,
116 ClojureProjectClj,
117
118 CpanDistIni,
120 CpanMakefile,
122 CpanManifest,
123 CpanMetaJson,
124 CpanMetaYml,
125
126 CranDescription,
128
129 PubspecLock,
131 PubspecYaml,
132
133 DebianControlExtractedDeb,
135 DebianControlInSource,
136 DebianCopyright,
137 DebianCopyrightInSource,
138 DebianCopyrightInPackage,
139 DebianCopyrightStandalone,
140 DebianDeb,
141 DebianSourceMetadataTarball,
143 DebianDistrolessInstalledDb,
144 DebianInstalledFilesList,
146 DebianInstalledMd5Sums,
147 DebianInstalledStatusDb,
148 DebianMd5SumsInExtractedDeb,
149 DebianOriginalSourceTarball,
151 DebianSourceControlDsc,
152
153 DenoJson,
155 DenoLock,
156
157 Dockerfile,
159
160 ErlangOtpAppSrc,
162 RebarConfig,
163 RebarLock,
164
165 FreebsdCompactManifest,
167
168 Godeps,
170 GoBinary,
171 GoMod,
172 GoModGraph,
173 GoSum,
174 GoWork,
175
176 HackageCabal,
178 HackageCabalProject,
179 HackageStackYaml,
180
181 BuildGradle,
183 GradleLockfile,
184 GradleModule,
185
186 HaxelibJson,
188
189 HelmChartLock,
191 HelmChartYaml,
192
193 HexMixLock,
195
196 JuliaProjectToml,
198 JuliaManifestToml,
199
200 AntIvyXml,
202 JavaEarApplicationXml,
203 JavaEarArchive,
204 JavaJar,
205 JavaJarManifest,
206 JavaOsgiManifest,
207 JavaWarArchive,
208 JavaWarWebXml,
209 JbossSar,
210 JbossServiceXml,
211
212 MavenPom,
214 MavenPomProperties,
215 MesonBuild,
216
217 SbtBuildSbt,
218
219 MicrosoftCabinet,
221 MicrosoftUpdateManifestMum,
222
223 AppleDmg,
225 ChromeCrx,
226 IosIpa,
227 MozillaXpi,
228
229 MeteorPackage,
231
232 NixDefaultNix,
233 NixFlakeLock,
234 NixFlakeNix,
235
236 NpmPackageJson,
238 NpmPackageLockJson,
239
240 NugetCsproj,
242 NugetDepsJson,
243 NugetDirectoryBuildProps,
244 NugetDirectoryPackagesProps,
245 NugetNupkg,
246 NugetProjectJson,
247 NugetProjectLockJson,
248 NugetPackagesConfig,
249 NugetPackagesLock,
250 NugetNuspec,
251 NugetVbproj,
252 NugetFsproj,
253
254 OpamFile,
256
257 PhpComposerJson,
259 PhpComposerLock,
260
261 PnpmLockYaml,
263 PnpmWorkspaceYaml,
264
265 Pipfile,
267 PipfileLock,
268 PipRequirements,
269 PixiLock,
270 PixiToml,
271 PypiPipOriginJson,
272 PypiEgg,
273 PypiEggPkginfo,
274 PypiEditableEggPkginfo,
275 PypiInspectDeplock,
276 PypiJson,
277 PypiPoetryLock,
278 PypiPoetryPyprojectToml,
279 PypiSdist,
280 PypiPylockToml,
281 PypiPyprojectToml,
282 PypiSdistPkginfo,
283 PypiSetupCfg,
284 PypiSetupPy,
285 PypiUvLock,
286 PypiWheel,
287 PypiWheelMetadata,
288
289 RpmArchive,
291 RpmInstalledDatabaseBdb,
292 RpmInstalledDatabaseNdb,
293 RpmInstalledDatabaseSqlite,
294 RpmMarinerManifest,
295 RpmPackageLicenses,
296 RpmSpecfile,
297 RpmYumdb,
298
299 Gemfile,
301 GemfileExtracted,
302 GemfileLock,
303 GemfileLockExtracted,
304 GemArchive,
305 GemArchiveExtracted,
307 Gemspec,
308 GemspecExtracted,
309 GemGemspecInstalledSpecifications,
310
311 InstallshieldInstaller,
313 IsoDiskImage,
314 NsisInstaller,
315 SharShellArchive,
316 SquashfsDiskImage,
317
318 SwiftPackageManifestJson,
320 SwiftPackageResolved,
321 SwiftPackageShowDependencies,
322
323 PubliccodeYaml,
324
325 VcpkgJson,
327
328 YarnLock,
330 YarnLockV1,
331 YarnLockV2,
332 YarnPnpCjs,
333
334 Gitmodules,
336}
337
338impl DatasourceId {
339 pub fn as_str(&self) -> &'static str {
343 match self {
344 Self::AboutFile => "about_file",
346 Self::Readme => "readme",
347 Self::EtcOsRelease => "etc_os_release",
348
349 Self::AlpineApkArchive => "alpine_apk_archive",
351 Self::AlpineApkbuild => "alpine_apkbuild",
352 Self::AlpineInstalledDb => "alpine_installed_db",
353
354 Self::ArchAurinfo => "arch_aurinfo",
356 Self::ArchPkginfo => "arch_pkginfo",
357 Self::ArchSrcinfo => "arch_srcinfo",
358
359 Self::AndroidAab => "android_aab",
361 Self::AndroidAarLibrary => "android_aar_library",
362 Self::AndroidApk => "android_apk",
363 Self::AndroidManifestXml => "android_manifest_xml",
364 Self::AndroidSoongMetadata => "android_soong_metadata",
365
366 Self::Axis2Mar => "axis2_mar",
368 Self::Axis2ModuleXml => "axis2_module_xml",
369
370 Self::AutotoolsConfigure => "autotools_configure",
372
373 Self::BazelBuild => "bazel_build",
375
376 Self::BitbakeRecipe => "bitbake_recipe",
378 Self::BitbakeRecipeAppend => "bitbake_recipe_append",
379
380 Self::BowerJson => "bower_json",
382
383 Self::BuckFile => "buck_file",
385 Self::BuckMetadata => "buck_metadata",
386
387 Self::CarthageCartfile => "carthage_cartfile",
389 Self::CarthageCartfileResolved => "carthage_cartfile_resolved",
390
391 Self::CargoLock => "cargo_lock",
393 Self::CargoToml => "cargo_toml",
394 Self::RustBinary => "rust_binary",
395 Self::WindowsExecutable => "windows_executable",
396
397 Self::ChefCookbookMetadataJson => "chef_cookbook_metadata_json",
399 Self::ChefCookbookMetadataRb => "chef_cookbook_metadata_rb",
400
401 Self::CitationCff => "citation_cff",
402
403 Self::CocoapodsPodfile => "cocoapods_podfile",
405 Self::CocoapodsPodfileLock => "cocoapods_podfile_lock",
406 Self::CocoapodsPodspec => "cocoapods_podspec",
407 Self::CocoapodsPodspecJson => "cocoapods_podspec_json",
408
409 Self::ConanConanDataYml => "conan_conandata_yml",
411 Self::ConanConanFilePy => "conan_conanfile_py",
412 Self::ConanConanFileTxt => "conan_conanfile_txt",
413 Self::ConanLock => "conan_lock",
414
415 Self::CondaYaml => "conda_yaml",
417 Self::CondaMetaJson => "conda_meta_json",
418 Self::CondaMetaYaml => "conda_meta_yaml",
419
420 Self::ClojureDepsEdn => "clojure_deps_edn",
422 Self::ClojureProjectClj => "clojure_project_clj",
423
424 Self::CpanDistIni => "cpan_dist_ini",
426 Self::CpanMakefile => "cpan_makefile",
427 Self::CpanManifest => "cpan_manifest",
428 Self::CpanMetaJson => "cpan_meta_json",
429 Self::CpanMetaYml => "cpan_meta_yml",
430
431 Self::CranDescription => "cran_description",
433
434 Self::PubspecLock => "pubspec_lock",
436 Self::PubspecYaml => "pubspec_yaml",
437
438 Self::DebianControlExtractedDeb => "debian_control_extracted_deb",
440 Self::DebianControlInSource => "debian_control_in_source",
441 Self::DebianCopyright => "debian_copyright",
442 Self::DebianCopyrightInSource => "debian_copyright_in_source",
443 Self::DebianCopyrightInPackage => "debian_copyright_in_package",
444 Self::DebianCopyrightStandalone => "debian_copyright_standalone",
445 Self::DebianDeb => "debian_deb",
446 Self::DebianSourceMetadataTarball => "debian_source_metadata_tarball",
447 Self::DebianDistrolessInstalledDb => "debian_distroless_installed_db",
448 Self::DebianInstalledFilesList => "debian_installed_files_list",
449 Self::DebianInstalledMd5Sums => "debian_installed_md5sums",
450 Self::DebianInstalledStatusDb => "debian_installed_status_db",
451 Self::DebianMd5SumsInExtractedDeb => "debian_md5sums_in_extracted_deb",
452 Self::DebianOriginalSourceTarball => "debian_original_source_tarball",
453 Self::DebianSourceControlDsc => "debian_source_control_dsc",
454 Self::DenoJson => "deno_json",
455 Self::DenoLock => "deno_lock",
456 Self::Dockerfile => "dockerfile",
457 Self::ErlangOtpAppSrc => "erlang_otp_app_src",
458 Self::RebarConfig => "rebar_config",
459 Self::RebarLock => "rebar_lock",
460 Self::BazelModule => "bazel_module",
461
462 Self::FreebsdCompactManifest => "freebsd_compact_manifest",
464
465 Self::Godeps => "godeps",
467 Self::GoBinary => "go_binary",
468 Self::GoMod => "go_mod",
469 Self::GoModGraph => "go_mod_graph",
470 Self::GoSum => "go_sum",
471 Self::GoWork => "go_work",
472
473 Self::HackageCabal => "hackage_cabal",
475 Self::HackageCabalProject => "hackage_cabal_project",
476 Self::HackageStackYaml => "hackage_stack_yaml",
477
478 Self::BuildGradle => "build_gradle",
480 Self::GradleLockfile => "gradle_lockfile",
481 Self::GradleModule => "gradle_module",
482
483 Self::HaxelibJson => "haxelib_json",
485
486 Self::HelmChartLock => "helm_chart_lock",
488 Self::HelmChartYaml => "helm_chart_yaml",
489
490 Self::HexMixLock => "hex_mix_lock",
492
493 Self::JuliaProjectToml => "julia_project_toml",
495 Self::JuliaManifestToml => "julia_manifest_toml",
496
497 Self::AntIvyXml => "ant_ivy_xml",
499 Self::JavaEarApplicationXml => "java_ear_application_xml",
500 Self::JavaEarArchive => "java_ear_archive",
501 Self::JavaJar => "java_jar",
502 Self::JavaJarManifest => "java_jar_manifest",
503 Self::JavaOsgiManifest => "java_osgi_manifest",
504 Self::JavaWarArchive => "java_war_archive",
505 Self::JavaWarWebXml => "java_war_web_xml",
506 Self::JbossSar => "jboss_sar",
507 Self::JbossServiceXml => "jboss_service_xml",
508
509 Self::MavenPom => "maven_pom",
511 Self::MavenPomProperties => "maven_pom_properties",
512 Self::MesonBuild => "meson_build",
513 Self::SbtBuildSbt => "sbt_build_sbt",
514
515 Self::MicrosoftCabinet => "microsoft_cabinet",
517 Self::MicrosoftUpdateManifestMum => "microsoft_update_manifest_mum",
518
519 Self::AppleDmg => "apple_dmg",
521 Self::ChromeCrx => "chrome_crx",
522 Self::IosIpa => "ios_ipa",
523 Self::MozillaXpi => "mozilla_xpi",
524
525 Self::MeteorPackage => "meteor_package",
527
528 Self::NixDefaultNix => "nix_default_nix",
529 Self::NixFlakeLock => "nix_flake_lock",
530 Self::NixFlakeNix => "nix_flake_nix",
531
532 Self::BunLock => "bun_lock",
534 Self::BunLockb => "bun_lockb",
535 Self::NpmPackageJson => "npm_package_json",
536 Self::NpmPackageLockJson => "npm_package_lock_json",
537
538 Self::NugetCsproj => "nuget_csproj",
540 Self::NugetDepsJson => "nuget_deps_json",
541 Self::NugetDirectoryBuildProps => "nuget_directory_build_props",
542 Self::NugetDirectoryPackagesProps => "nuget_directory_packages_props",
543 Self::NugetNupkg => "nuget_nupkg",
544 Self::NugetProjectJson => "nuget_project_json",
545 Self::NugetProjectLockJson => "nuget_project_lock_json",
546 Self::NugetPackagesConfig => "nuget_packages_config",
547 Self::NugetPackagesLock => "nuget_packages_lock",
548 Self::NugetNuspec => "nuget_nuspec",
549 Self::NugetVbproj => "nuget_vbproj",
550 Self::NugetFsproj => "nuget_fsproj",
551
552 Self::OpamFile => "opam_file",
554
555 Self::PhpComposerJson => "php_composer_json",
557 Self::PhpComposerLock => "php_composer_lock",
558
559 Self::PnpmLockYaml => "pnpm_lock_yaml",
561 Self::PnpmWorkspaceYaml => "pnpm_workspace_yaml",
562
563 Self::Pipfile => "pipfile",
565 Self::PipfileLock => "pipfile_lock",
566 Self::PipRequirements => "pip_requirements",
567 Self::PixiLock => "pixi_lock",
568 Self::PixiToml => "pixi_toml",
569 Self::PypiPipOriginJson => "pypi_pip_origin_json",
570 Self::PypiEgg => "pypi_egg",
571 Self::PypiEggPkginfo => "pypi_egg_pkginfo",
572 Self::PypiEditableEggPkginfo => "pypi_editable_egg_pkginfo",
573 Self::PypiInspectDeplock => "pypi_inspect_deplock",
574 Self::PypiJson => "pypi_json",
575 Self::PypiPoetryLock => "pypi_poetry_lock",
576 Self::PypiPoetryPyprojectToml => "pypi_poetry_pyproject_toml",
577 Self::PypiSdist => "pypi_sdist",
578 Self::PypiPylockToml => "pypi_pylock_toml",
579 Self::PypiPyprojectToml => "pypi_pyproject_toml",
580 Self::PypiSdistPkginfo => "pypi_sdist_pkginfo",
581 Self::PypiSetupCfg => "pypi_setup_cfg",
582 Self::PypiSetupPy => "pypi_setup_py",
583 Self::PypiUvLock => "pypi_uv_lock",
584 Self::PypiWheel => "pypi_wheel",
585 Self::PypiWheelMetadata => "pypi_wheel_metadata",
586
587 Self::RpmArchive => "rpm_archive",
589 Self::RpmInstalledDatabaseBdb => "rpm_installed_database_bdb",
590 Self::RpmInstalledDatabaseNdb => "rpm_installed_database_ndb",
591 Self::RpmInstalledDatabaseSqlite => "rpm_installed_database_sqlite",
592 Self::RpmMarinerManifest => "rpm_mariner_manifest",
593 Self::RpmPackageLicenses => "rpm_package_licenses",
594 Self::RpmSpecfile => "rpm_specfile",
595 Self::RpmYumdb => "rpm_yumdb",
596
597 Self::Gemfile => "gemfile",
599 Self::GemfileExtracted => "gemfile_extracted",
600 Self::GemfileLock => "gemfile_lock",
601 Self::GemfileLockExtracted => "gemfile_lock_extracted",
602 Self::GemArchive => "gem_archive",
603 Self::GemArchiveExtracted => "gem_archive_extracted",
604 Self::Gemspec => "gemspec",
605 Self::GemspecExtracted => "gemspec_extracted",
606 Self::GemGemspecInstalledSpecifications => "gem_gemspec_installed_specifications",
607
608 Self::InstallshieldInstaller => "installshield_installer",
610 Self::IsoDiskImage => "iso_disk_image",
611 Self::NsisInstaller => "nsis_installer",
612 Self::SharShellArchive => "shar_shell_archive",
613 Self::SquashfsDiskImage => "squashfs_disk_image",
614
615 Self::SwiftPackageManifestJson => "swift_package_manifest_json",
617 Self::SwiftPackageResolved => "swift_package_resolved",
618 Self::SwiftPackageShowDependencies => "swift_package_show_dependencies",
619
620 Self::PubliccodeYaml => "publiccode_yaml",
621
622 Self::VcpkgJson => "vcpkg_json",
624
625 Self::YarnLock => "yarn_lock",
627 Self::YarnLockV1 => "yarn_lock_v1",
628 Self::YarnLockV2 => "yarn_lock_v2",
629 Self::YarnPnpCjs => "yarn_pnp_cjs",
630
631 Self::Gitmodules => "gitmodules",
633 }
634 }
635}
636
637impl AsRef<str> for DatasourceId {
638 fn as_ref(&self) -> &str {
639 self.as_str()
640 }
641}
642
643impl fmt::Display for DatasourceId {
644 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
645 f.write_str(self.as_str())
646 }
647}
648
649impl FromStr for DatasourceId {
650 type Err = String;
651
652 fn from_str(s: &str) -> Result<Self, Self::Err> {
653 use strum::IntoEnumIterator;
654 Self::iter()
655 .find(|variant| variant.as_str() == s)
656 .ok_or_else(|| format!("unknown datasource id: {}", s))
657 }
658}
659
660#[cfg(test)]
661mod tests {
662 use super::*;
663
664 #[test]
665 fn test_serialization() {
666 let id = DatasourceId::NpmPackageJson;
667 let json = serde_json::to_string(&id).unwrap();
668 assert_eq!(json, r#""NpmPackageJson""#);
669 }
670
671 #[test]
672 fn test_deserialization() {
673 let json = r#""NpmPackageJson""#;
674 let id: DatasourceId = serde_json::from_str(json).unwrap();
675 assert_eq!(id, DatasourceId::NpmPackageJson);
676 }
677
678 #[test]
679 fn test_as_str() {
680 assert_eq!(DatasourceId::NpmPackageJson.as_str(), "npm_package_json");
681 assert_eq!(DatasourceId::CargoLock.as_str(), "cargo_lock");
682 assert_eq!(
683 DatasourceId::PypiPyprojectToml.as_str(),
684 "pypi_pyproject_toml"
685 );
686 assert_eq!(DatasourceId::HackageCabal.as_str(), "hackage_cabal");
687 assert_eq!(DatasourceId::CitationCff.as_str(), "citation_cff");
688 assert_eq!(DatasourceId::PubliccodeYaml.as_str(), "publiccode_yaml");
689 assert_eq!(DatasourceId::YarnPnpCjs.as_str(), "yarn_pnp_cjs");
690 }
691
692 #[test]
693 fn test_display() {
694 assert_eq!(DatasourceId::NpmPackageJson.to_string(), "npm_package_json");
695 }
696
697 #[test]
698 fn test_as_ref() {
699 let id = DatasourceId::NpmPackageJson;
700 let s: &str = id.as_ref();
701 assert_eq!(s, "npm_package_json");
702 }
703
704 #[test]
705 fn test_python_rename_mappings() {
706 assert_eq!(DatasourceId::BuckFile.as_str(), "buck_file");
708 assert_eq!(DatasourceId::BuckMetadata.as_str(), "buck_metadata");
709 assert_eq!(
710 DatasourceId::ChefCookbookMetadataJson.as_str(),
711 "chef_cookbook_metadata_json"
712 );
713 assert_eq!(
714 DatasourceId::ChefCookbookMetadataRb.as_str(),
715 "chef_cookbook_metadata_rb"
716 );
717 assert_eq!(DatasourceId::CondaYaml.as_str(), "conda_yaml");
718 assert_eq!(DatasourceId::CpanMakefile.as_str(), "cpan_makefile");
719 assert_eq!(
720 DatasourceId::DebianInstalledFilesList.as_str(),
721 "debian_installed_files_list"
722 );
723 assert_eq!(
724 DatasourceId::DebianOriginalSourceTarball.as_str(),
725 "debian_original_source_tarball"
726 );
727 assert_eq!(
728 DatasourceId::DebianSourceMetadataTarball.as_str(),
729 "debian_source_metadata_tarball"
730 );
731 assert_eq!(
732 DatasourceId::GemArchiveExtracted.as_str(),
733 "gem_archive_extracted"
734 );
735 assert_eq!(DatasourceId::NugetNuspec.as_str(), "nuget_nuspec");
737 assert_eq!(DatasourceId::RpmSpecfile.as_str(), "rpm_specfile");
738 }
739
740 #[test]
741 fn test_canonical_serialization() {
742 let nuget_json = serde_json::to_string(&DatasourceId::NugetNuspec).unwrap();
743 assert_eq!(nuget_json, r#""NugetNuspec""#);
744
745 let rpm_json = serde_json::to_string(&DatasourceId::RpmSpecfile).unwrap();
746 assert_eq!(rpm_json, r#""RpmSpecfile""#);
747 }
748
749 #[test]
750 fn test_from_str_uses_canonical_ids_and_rejects_legacy_typos() {
751 assert_eq!(
752 DatasourceId::from_str("nuget_nuspec").unwrap(),
753 DatasourceId::NugetNuspec
754 );
755 assert_eq!(
756 DatasourceId::from_str("rpm_specfile").unwrap(),
757 DatasourceId::RpmSpecfile
758 );
759 assert!(DatasourceId::from_str("nuget_nupsec").is_err());
763 assert!(DatasourceId::from_str("rpm_spefile").is_err());
764 }
765}