1use crate::Purl;
2use semver::VersionReq;
3use std::{
4 borrow::Cow,
5 collections::HashMap,
6 fmt,
7 path::{Path, PathBuf},
8};
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub enum Unit {
13 Project { manifest: PathBuf, name: String },
15 Workspace { manifest: PathBuf },
17 Global,
19}
20
21impl Ord for Unit {
22 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
23 match (self, other) {
24 (Unit::Workspace { .. }, Unit::Workspace { .. }) => std::cmp::Ordering::Equal,
25 (Unit::Workspace { .. }, _) => std::cmp::Ordering::Less,
26 (_, Unit::Workspace { .. }) => std::cmp::Ordering::Greater,
27 (Unit::Global, Unit::Global) => std::cmp::Ordering::Equal,
28 (Unit::Global, _) => std::cmp::Ordering::Greater,
29 (_, Unit::Global) => std::cmp::Ordering::Less,
30 _ => self.name().cmp(&other.name()),
31 }
32 }
33}
34
35impl PartialOrd for Unit {
36 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
37 Some(self.cmp(other))
38 }
39}
40
41impl Unit {
42 pub fn path(&self) -> Option<&Path> {
44 match self {
45 Unit::Project { manifest, .. } | Unit::Workspace { manifest, .. } => Some(manifest),
46 Unit::Global => None,
47 }
48 }
49
50 pub fn name(&self) -> Cow<'_, str> {
52 match self {
53 Unit::Project { name, .. } => name.into(),
54 Unit::Workspace { manifest, .. } => manifest
55 .parent()
56 .and_then(|p| p.file_name())
57 .and_then(|n| n.to_str())
58 .map(|n| format!("{n} (workspace)"))
59 .unwrap_or("workspace".into())
60 .into(),
61 Unit::Global => "global".into(),
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68pub enum DepKind {
69 Normal,
70 Dev,
71 Build,
72}
73
74impl fmt::Display for DepKind {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 DepKind::Normal => write!(f, "dependencies"),
78 DepKind::Dev => write!(f, "dev-dependencies"),
79 DepKind::Build => write!(f, "build-dependencies"),
80 }
81 }
82}
83
84#[derive(Debug, Clone)]
85pub struct Usage {
86 pub unit: Unit,
87 pub req: VersionReq,
88 pub kind: DepKind,
89 pub rename: Option<String>,
90}
91
92#[derive(Debug, Clone)]
93pub struct Package {
94 pub purl: Purl,
95 pub usages: Vec<Usage>,
96 pub versions: Vec<PackageVersion>,
97 pub repository: Option<String>,
98 pub homepage: Option<String>,
99}
100
101pub type Packages = HashMap<Unit, Vec<(VersionReq, DepKind, Package)>>;
102
103#[derive(Debug, Clone)]
104pub struct PackageVersion {
105 pub version: semver::Version,
106 pub yanked: bool,
107 pub features: HashMap<String, Vec<String>>,
108 pub rust_version: Option<semver::Version>,
109}