use std::collections::HashMap;
use bstr::BString;
use smartstring::alias::String as SmolString;
use std::hash::Hash;
use std::{fmt, slice};
pub struct Index {
pub seen_ref_name: &'static str,
pub branch_name: &'static str,
pub remote_name: Option<BString>,
pub(crate) repo: gix::Repository,
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Change {
Added(CrateVersion),
Unyanked(CrateVersion),
AddedAndYanked(CrateVersion),
Yanked(CrateVersion),
CrateDeleted {
name: String,
versions: Vec<CrateVersion>,
},
VersionDeleted(CrateVersion),
}
impl Change {
pub fn added(&self) -> Option<&CrateVersion> {
match self {
Change::Added(v) | Change::AddedAndYanked(v) => Some(v),
_ => None,
}
}
pub fn yanked(&self) -> Option<&CrateVersion> {
match self {
Change::Yanked(v) | Change::AddedAndYanked(v) => Some(v),
_ => None,
}
}
pub fn unyanked(&self) -> Option<&CrateVersion> {
match self {
Change::Unyanked(v) => Some(v),
_ => None,
}
}
pub fn crate_deleted(&self) -> Option<(&str, &[CrateVersion])> {
match self {
Change::CrateDeleted { name, versions } => Some((name.as_str(), versions)),
_ => None,
}
}
pub fn version_deleted(&self) -> Option<&CrateVersion> {
match self {
Change::VersionDeleted(v) => Some(v),
_ => None,
}
}
pub fn versions(&self) -> &[CrateVersion] {
match self {
Change::Added(v)
| Change::Unyanked(v)
| Change::AddedAndYanked(v)
| Change::Yanked(v)
| Change::VersionDeleted(v) => slice::from_ref(v),
Change::CrateDeleted { versions, .. } => versions,
}
}
}
impl fmt::Display for Change {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match *self {
Change::Added(_) => "added",
Change::Yanked(_) => "yanked",
Change::CrateDeleted { .. } => "crate deleted",
Change::VersionDeleted(_) => "version deleted",
Change::Unyanked(_) => "unyanked",
Change::AddedAndYanked(_) => "added and yanked",
}
)
}
}
#[derive(
Debug, Copy, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Ord, PartialOrd,
)]
#[serde(rename_all = "lowercase")]
pub enum DependencyKind {
Normal,
Dev,
Build,
}
#[derive(Default, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Debug)]
pub struct CrateVersion {
pub name: SmolString,
pub yanked: bool,
#[serde(rename = "vers")]
pub version: SmolString,
#[serde(rename = "cksum", with = "hex")]
pub checksum: [u8; 32],
pub features: HashMap<String, Vec<String>>,
#[serde(rename = "deps")]
pub dependencies: Vec<Dependency>,
}
impl CrateVersion {
#[cfg(feature = "semver")]
pub fn version(&self) -> semver::Version {
semver::Version::parse(&self.version)
.expect("crate index guarantees a valid semantic version")
}
}
#[derive(
Clone, serde::Serialize, serde::Deserialize, Ord, PartialOrd, Eq, PartialEq, Debug, Hash,
)]
pub struct Dependency {
pub name: SmolString,
#[serde(rename = "req")]
pub required_version: SmolString,
pub features: Vec<String>,
pub optional: bool,
pub default_features: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<SmolString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<DependencyKind>,
#[serde(skip_serializing_if = "Option::is_none")]
pub package: Option<SmolString>,
}
impl Dependency {
#[cfg(feature = "semver")]
pub fn required_version(&self) -> semver::VersionReq {
semver::VersionReq::parse(&self.required_version)
.expect("version requirement should always be a valid SemVer")
}
}