From 9212f95417473c2be7087fc4a5e448fe8169a5cc Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Mon, 2 Feb 2026 21:33:27 +0000 Subject: [PATCH] Add Go and Rust parsers --- depaudit/parsers/rust.py | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 depaudit/parsers/rust.py diff --git a/depaudit/parsers/rust.py b/depaudit/parsers/rust.py new file mode 100644 index 0000000..97bb3a2 --- /dev/null +++ b/depaudit/parsers/rust.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import tomllib +from pathlib import Path +from typing import Any + +from depaudit.parsers import Parser, ParsedManifest, Dependency + + +class RustParser(Parser): + language = "rust" + + def can_parse(self, file_path: Path) -> bool: + return file_path.name in ("Cargo.toml", "Cargo.lock") + + def parse(self, file_path: Path) -> ParsedManifest: + with open(file_path, "rb") as f: + data = tomllib.load(f) + + manifest = ParsedManifest( + language=self.language, + file_path=file_path, + ) + + if file_path.name == "Cargo.toml": + self._parse_cargo_toml(file_path, data, manifest) + elif file_path.name == "Cargo.lock": + self._parse_cargo_lock(file_path, data, manifest) + + return manifest + + def _parse_cargo_toml( + self, file_path: Path, data: dict[str, Any], manifest: ParsedManifest + ) -> None: + manifest.project_name = data.get("package", {}).get("name") + manifest.project_version = data.get("package", {}).get("version") + + dependencies = data.get("dependencies", {}) + for name, dep_info in dependencies.items(): + if isinstance(dep_info, str): + version = dep_info + manifest.dependencies.append( + self._create_dependency(file_path, name, version) + ) + elif isinstance(dep_info, dict): + version = dep_info.get("version", "") + optional = dep_info.get("optional", False) + manifest.dependencies.append( + self._create_dependency( + file_path, name, version, optional=optional + ) + ) + + dev_dependencies = data.get("dev-dependencies", {}) + for name, dep_info in dev_dependencies.items(): + if isinstance(dep_info, str): + version = dep_info + manifest.dependencies.append( + self._create_dependency(file_path, name, version, dev=True) + ) + elif isinstance(dep_info, dict): + version = dep_info.get("version", "") + manifest.dependencies.append( + self._create_dependency(file_path, name, version, dev=True) + ) + + build_dependencies = data.get("build-dependencies", {}) + for name, dep_info in build_dependencies.items(): + if isinstance(dep_info, str): + version = dep_info + manifest.dependencies.append( + self._create_dependency(file_path, name, version, dev=True) + ) + elif isinstance(dep_info, dict): + version = dep_info.get("version", "") + manifest.dependencies.append( + self._create_dependency(file_path, name, version, dev=True) + ) + + manifest.raw_data = data + + def _parse_cargo_lock( + self, file_path: Path, data: dict[str, Any], manifest: ParsedManifest + ) -> None: + package = data.get("package", []) + for pkg in package: + name = pkg.get("name", "") + version = pkg.get("version", "") + source = pkg.get("source", "") + + if source and ("registry" in source or "git" in source or "local" in source): + manifest.dependencies.append( + self._create_dependency(file_path, name, version) + )