use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExactFallbackReceipt {
pub raw_digest: Digest,
pub compressed_digest: Digest,
pub fallback_retention: bool,
pub fallback_reason: Option<String>,
}
impl ExactFallbackReceipt {
pub fn new(raw_digest: Digest, compressed_digest: Digest, fallback_retention: bool) -> Self {
Self {
raw_digest,
compressed_digest,
fallback_retention,
fallback_reason: None,
}
}
pub fn with_reason(
raw_digest: Digest,
compressed_digest: Digest,
fallback_retention: bool,
reason: impl Into<String>,
) -> Self {
Self {
raw_digest,
compressed_digest,
fallback_retention,
fallback_reason: Some(reason.into()),
}
}
pub fn bytes_saved(&self) -> Option<u64> {
None
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Digest {
pub algorithm: DigestAlgorithm,
pub value: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DigestAlgorithm {
Sha256,
Blake3,
}
impl Digest {
pub fn sha256(value: impl Into<String>) -> Self {
Self {
algorithm: DigestAlgorithm::Sha256,
value: value.into(),
}
}
pub fn blake3(value: impl Into<String>) -> Self {
Self {
algorithm: DigestAlgorithm::Blake3,
value: value.into(),
}
}
}
impl std::fmt::Display for DigestAlgorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DigestAlgorithm::Sha256 => write!(f, "sha256"),
DigestAlgorithm::Blake3 => write!(f, "blake3"),
}
}
}
impl std::fmt::Display for Digest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.algorithm, self.value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn digest_creation() {
let d = Digest::sha256("abc123");
assert_eq!(d.algorithm, DigestAlgorithm::Sha256);
assert_eq!(d.value, "abc123");
}
#[test]
fn fallback_receipt_display() {
let receipt =
ExactFallbackReceipt::new(Digest::sha256("raw"), Digest::blake3("compressed"), true);
assert!(receipt.fallback_retention);
}
}