use serde::{Deserialize, Serialize};
use std::path::Path;
use uv_distribution_types::Hashed;
use uv_pypi_types::{HashDigest, HashDigests};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct Revision {
id: RevisionId,
hashes: HashDigests,
}
impl Revision {
pub(crate) fn new() -> Self {
Self {
id: RevisionId::new(),
hashes: HashDigests::empty(),
}
}
pub(crate) fn id(&self) -> &RevisionId {
&self.id
}
pub(crate) fn hashes(&self) -> &[HashDigest] {
self.hashes.as_slice()
}
pub(crate) fn into_hashes(self) -> HashDigests {
self.hashes
}
#[must_use]
pub(crate) fn with_hashes(mut self, hashes: HashDigests) -> Self {
self.hashes = hashes;
self
}
}
impl Hashed for Revision {
fn hashes(&self) -> &[HashDigest] {
self.hashes.as_slice()
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) struct RevisionId(String);
impl RevisionId {
fn new() -> Self {
Self(uv_fastid::insecure().to_string())
}
pub(crate) fn as_str(&self) -> &str {
&self.0
}
}
impl AsRef<str> for RevisionId {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
impl AsRef<Path> for RevisionId {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_legacy_nanoid_revision() {
let legacy = Revision {
id: RevisionId("HM0NxJml5hc7UjbfTWT1r".to_string()),
hashes: HashDigests::empty(),
};
let bytes = rmp_serde::to_vec(&legacy).expect("serialize legacy revision");
let parsed: Revision = rmp_serde::from_slice(&bytes).expect("deserialize legacy revision");
assert_eq!(parsed.id().as_str(), "HM0NxJml5hc7UjbfTWT1r");
}
#[test]
fn round_trip_current_revision() {
let original = Revision::new();
let bytes = rmp_serde::to_vec(&original).expect("serialize revision");
let parsed: Revision = rmp_serde::from_slice(&bytes).expect("deserialize revision");
assert_eq!(parsed.id().as_str(), original.id().as_str());
}
}