use thiserror::Error;
pub const MAGIC: &[u8; 4] = b"NDBB";
pub const VERSION: u8 = 1;
pub const HEADER_LEN: usize = 52;
pub const SECTION_OVERHEAD: usize = 16;
pub const TRAILER_LEN: usize = 4;
pub const DEFAULT_MAX_TOTAL_BYTES: u64 = 16 * 1024 * 1024 * 1024;
pub const DEFAULT_MAX_SECTION_BYTES: u64 = 16 * 1024 * 1024 * 1024;
pub const SECTION_ORIGIN_CATALOG_ROWS: u64 = 0xFFFF_FFFF_FFFF_FFF0;
pub const SECTION_ORIGIN_SOURCE_TOMBSTONES: u64 = 0xFFFF_FFFF_FFFF_FFF1;
#[derive(Debug, Clone, PartialEq, Eq, zerompk::ToMessagePack, zerompk::FromMessagePack)]
pub struct StoredCollectionBlob {
pub name: String,
pub bytes: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, zerompk::ToMessagePack, zerompk::FromMessagePack)]
pub struct SourceTombstoneEntry {
pub collection: String,
pub purge_lsn: u64,
}
#[derive(Debug, Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum EnvelopeError {
#[error("invalid backup format")]
BadMagic,
#[error("unsupported backup version: {0}")]
UnsupportedVersion(u8),
#[error("invalid backup format")]
HeaderCrcMismatch,
#[error("invalid backup format")]
BodyCrcMismatch,
#[error("invalid backup format")]
TrailerCrcMismatch,
#[error("backup truncated")]
Truncated,
#[error("backup tenant mismatch: expected {expected}, got {actual}")]
TenantMismatch { expected: u64, actual: u64 },
#[error("backup exceeds size cap of {cap} bytes")]
OverSizeTotal { cap: u64 },
#[error("backup section exceeds size cap of {cap} bytes")]
OverSizeSection { cap: u64 },
#[error("too many sections: {0}")]
TooManySections(u16),
#[error("wrong backup KEK: presented key fingerprint does not match envelope")]
WrongBackupKek,
#[error("backup decryption failed: authentication tag mismatch")]
DecryptionFailed,
#[error("backup encryption failed")]
EncryptionFailed,
#[error("backup encryption failed: {0}")]
RandomFailure(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EnvelopeMeta {
pub tenant_id: u64,
pub source_vshard_count: u16,
pub hash_seed: u64,
pub snapshot_watermark: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Section {
pub origin_node_id: u64,
pub body: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Envelope {
pub meta: EnvelopeMeta,
pub sections: Vec<Section>,
}
pub fn read2(s: &[u8]) -> [u8; 2] {
[s[0], s[1]]
}
pub fn read4(s: &[u8]) -> [u8; 4] {
[s[0], s[1], s[2], s[3]]
}
pub fn read8(s: &[u8]) -> [u8; 8] {
[s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]]
}