use crate::chunk::ChunkParams;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;
fn bytebuf_is_empty(b: &ByteBuf) -> bool {
b.as_ref().is_empty()
}
fn is_zero_u8(x: &u8) -> bool {
*x == 0
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChunkRef {
pub h: ByteBuf,
pub s: u32,
#[serde(default, skip_serializing_if = "is_zero_u8")]
pub x: u8,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RefArchive {
pub root: ByteBuf,
pub hint: String,
pub chunks: u32,
pub bytes: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlobRecord {
pub off: u64,
pub clen: u32,
pub ulen: u32,
pub codec: u8,
pub n: Vec<u32>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub p: Vec<u32>,
#[serde(default, skip_serializing_if = "is_zero_u8")]
pub f: u8,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub d: Vec<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct ChunkIndex {
pub chunks: Vec<ChunkRef>,
pub blobs: Vec<BlobRecord>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Limits {
pub max_total: u64,
pub max_entry: u64,
pub max_ratio: u32,
}
impl Default for Limits {
fn default() -> Self {
Self { max_total: 4 << 30, max_entry: 1 << 30, max_ratio: 1000 }
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ZipMemberMeta {
pub name: String,
pub kind: u8,
pub local_header: ByteBuf,
#[serde(default, skip_serializing_if = "bytebuf_is_empty")]
pub descriptor: ByteBuf,
pub central: ByteBuf,
#[serde(default, skip_serializing_if = "bytebuf_is_empty")]
pub corrections: ByteBuf,
pub size: u64,
pub chunks: Vec<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ZipRecipe {
pub local_order: Vec<u32>,
pub eocd: ByteBuf,
pub members: Vec<ZipMemberMeta>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StreamSegment {
pub kind: u8,
#[serde(default, skip_serializing_if = "bytebuf_is_empty")]
pub header: ByteBuf,
#[serde(default, skip_serializing_if = "bytebuf_is_empty")]
pub trailer: ByteBuf,
#[serde(default, skip_serializing_if = "bytebuf_is_empty")]
pub corrections: ByteBuf,
pub size: u64,
pub chunks: Vec<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StreamRecipe {
pub segments: Vec<StreamSegment>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Derived {
pub from: String,
pub view: String,
pub generator: String,
pub tokens_est: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Entry {
pub path: String,
pub size: u64,
pub h: ByteBuf,
pub mode: String,
#[serde(default)]
pub chunks: Vec<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mtime: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub zip: Option<ZipRecipe>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub streams: Option<StreamRecipe>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub derived: Option<Derived>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Manifest {
pub tsaur: u16,
pub profile: String,
pub fidelity: String,
pub chunking: ChunkParams,
pub solid_block: u32,
pub limits: Limits,
pub root: ByteBuf,
pub entries: Vec<Entry>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created: Option<u64>,
#[serde(default)]
pub generator: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub refs: Vec<RefArchive>,
}