cargo_client 0.13.0

Cargo registry (crates.io) client
Documentation
use async_trait::async_trait;
use auto_impl::auto_impl;
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use thiserror::Error;
use url::Url;

#[cfg(feature = "http")]
pub mod http;

#[async_trait]
#[auto_impl(&, Arc)]
pub trait CargoClient: Send + Sync {
  async fn get_crate(&self, req: GetCrateRequestView<'_>) -> Result<ExtendedCrate, GetCrateError>;
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Error)]
pub enum GetCrateError {
  #[error("failed to send `GetCrate` request: {0}")]
  Send(String),
  #[error("failed to receive `GetCrate` response: {0}")]
  Receive(String),
  #[error("crate not found")]
  NotFound,
  #[error("unexpected `GetCrate` error: {0}")]
  Other(String),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetCrateRequest<Str = String> {
  pub name: Str,
}

pub type GetCrateRequestView<'req> = GetCrateRequest<&'req str>;

/// Extended crate data
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtendedCrate {
  pub categories: Vec<Category>,
  // `crate` is not a valid identifier (even using raw syntax)
  #[serde(rename = "crate")]
  pub krate: Crate,
  pub keywords: Vec<Keyword>,
  pub versions: Vec<CrateVersion>,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Category {
  pub category: String,
  pub crates_cnt: u64,
  pub created_at: DateTime<Utc>,
  pub description: String,
  pub id: String,
  pub slug: String,
}

/// Base crate data
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Crate {
  // pub badges: Vec<_>,
  pub categories: Vec<String>,
  pub created_at: DateTime<Utc>,
  pub description: String,
  pub documentation: Option<Url>,
  pub downloads: u64,
  pub exact_match: bool,
  pub homepage: Option<Url>,
  pub id: String,
  pub keywords: Vec<String>,
  pub links: CrateLinks,
  pub max_stable_version: String,
  pub max_version: String,
  pub name: String,
  pub newest_version: String,
  pub recent_downloads: Option<u64>,
  pub repository: Option<Url>,
  pub updated_at: DateTime<Utc>,
  pub versions: Vec<u64>,
}

// path urls (not full)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct CrateLinks {
  pub owner_team: String,
  pub owner_user: String,
  pub owners: String,
  pub reverse_dependencies: String,
  pub version_downloads: String,
  pub versions: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Keyword {
  pub crates_cnt: u64,
  pub created_at: DateTime<Utc>,
  pub id: String,
  pub keyword: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CrateVersion {
  pub audit_actions: Vec<AuditAction>,
  pub checksum: String,
  // `crate` is not a valid identifier (even using raw syntax)
  #[serde(rename = "crate")]
  pub krate: String,
  pub crate_size: u64,
  pub created_at: DateTime<Utc>,
  pub dl_path: String,
  pub downloads: u64,
  pub features: IndexMap<String, Vec<String>>,
  pub id: u64,
  pub license: Option<String>,
  pub links: VersionLinks,
  pub num: String,
  pub published_by: User,
  pub readme_path: Option<String>,
  pub rust_version: Option<String>,
  pub updated_at: DateTime<Utc>,
  pub yanked: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct AuditAction {
  action: String,
  time: DateTime<Utc>,
  user: User,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct VersionLinks {
  pub authors: String,
  pub dependencies: String,
  pub version_downloads: String,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct User {
  pub avatar: Option<Url>,
  pub email: Option<String>,
  pub id: u64,
  pub kind: Option<String>,
  pub login: String,
  pub name: String,
  pub url: Url,
}