use serde::{Deserialize, Serialize};
use crate::digest::Digest;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlobCheckRequest {
pub digests: Vec<Digest>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct BlobCheckResponse {
pub missing: Vec<Digest>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MissingBlob {
pub key: String,
pub digest: Digest,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MissingBlobsError {
pub message: String,
pub missing: Vec<MissingBlob>,
}
#[cfg(test)]
mod tests {
use super::*;
fn digest(byte: u8) -> Digest {
Digest::from_sha256([byte; 32])
}
#[test]
fn blob_check_round_trips_through_json() {
let req = BlobCheckRequest {
digests: vec![digest(1), digest(2)],
};
let json = serde_json::to_string(&req).unwrap();
assert_eq!(
serde_json::from_str::<BlobCheckRequest>(&json).unwrap(),
req
);
let res = BlobCheckResponse {
missing: vec![digest(2)],
};
let json = serde_json::to_string(&res).unwrap();
assert_eq!(
serde_json::from_str::<BlobCheckResponse>(&json).unwrap(),
res
);
}
#[test]
fn empty_blob_check_response_means_nothing_is_missing() {
let res: BlobCheckResponse = serde_json::from_str(r#"{"missing":[]}"#).unwrap();
assert_eq!(res, BlobCheckResponse::default());
assert!(res.missing.is_empty());
}
#[test]
fn missing_blobs_error_round_trips_through_json() {
let err = MissingBlobsError {
message: "2 assets are not on the server".to_string(),
missing: vec![
MissingBlob {
key: "img/logo.png".to_string(),
digest: digest(1),
},
MissingBlob {
key: "typst/layouts/pdf/hero.typ".to_string(),
digest: digest(2),
},
],
};
let json = serde_json::to_string(&err).unwrap();
assert_eq!(
serde_json::from_str::<MissingBlobsError>(&json).unwrap(),
err
);
}
#[test]
fn missing_blobs_error_rejects_an_invalid_digest() {
let err = serde_json::from_str::<MissingBlobsError>(
r#"{"message":"m","missing":[{"key":"k","digest":"NOPE"}]}"#,
)
.unwrap_err();
assert!(err.to_string().contains("64 hex characters"), "{err}");
}
}