use std::io::Read;
use crate::error::PqfileError;
use crate::format::{
version_layout, PqfHeader, PqfHeaderV10, PqfHeaderV4, PqfHeaderV7, PqfHeaderV8, NONCE_LEN,
VERSION, VERSION_AUTH_BIT, VERSION_V10, VERSION_V3, VERSION_V4, VERSION_V5, VERSION_V6,
VERSION_V7, VERSION_V8, VERSION_V9,
};
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct RecipientInfo {
pub kem_variant: u16,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum PqfHeaderInfo {
Single {
version: u8,
kem_variant: u16,
nonce: [u8; NONCE_LEN],
original_size: u64,
chunk_size: u32,
compression_algo: u8,
},
Multi {
recipients: Vec<RecipientInfo>,
nonce: [u8; NONCE_LEN],
original_size: u64,
},
AnonMulti {
recipients: Vec<RecipientInfo>,
nonce: [u8; NONCE_LEN],
original_size: u64,
},
AnonMultiV8 {
version: u8,
slot_count: usize,
nonce: [u8; NONCE_LEN],
original_size: u64,
},
Passphrase {
version: u8,
m_kib: u32,
t_cost: u32,
p_cost: u32,
flags: u8,
nonce: [u8; NONCE_LEN],
original_size: u64,
},
}
#[must_use = "inspect result must be used"]
pub fn inspect_stream<R: Read>(reader: &mut R) -> Result<PqfHeaderInfo, PqfileError> {
let version = PqfHeader::read_magic_version(reader)?;
if version == VERSION | VERSION_AUTH_BIT {
return Err(PqfileError::UnsupportedVersion(version));
}
match version_layout(version) {
VERSION | VERSION_V3 | VERSION_V5 | VERSION_V6 => {
let h = PqfHeader::read_body(reader, version)?;
Ok(PqfHeaderInfo::Single {
version: h.version,
kem_variant: h.kem_variant,
nonce: h.nonce,
original_size: h.original_size,
chunk_size: h.chunk_size,
compression_algo: h.compression_algo,
})
}
VERSION_V4 => {
let h = PqfHeaderV4::read_body(reader)?;
Ok(PqfHeaderInfo::Multi {
recipients: h
.recipients
.iter()
.map(|r| RecipientInfo {
kem_variant: r.kem_variant,
})
.collect(),
nonce: h.nonce,
original_size: h.original_size,
})
}
VERSION_V7 => {
let h = PqfHeaderV7::read_body(reader)?;
Ok(PqfHeaderInfo::AnonMulti {
recipients: h
.recipients
.iter()
.map(|r| RecipientInfo {
kem_variant: r.kem_variant,
})
.collect(),
nonce: h.nonce,
original_size: h.original_size,
})
}
VERSION_V8 | VERSION_V9 => {
let h = PqfHeaderV8::read_body(reader)?;
Ok(PqfHeaderInfo::AnonMultiV8 {
version,
slot_count: h.recipients.len(),
nonce: h.nonce,
original_size: h.original_size,
})
}
VERSION_V10 => {
let h = PqfHeaderV10::read_body(reader)?;
Ok(PqfHeaderInfo::Passphrase {
version,
m_kib: h.m_kib,
t_cost: h.t_cost,
p_cost: h.p_cost,
flags: h.flags,
nonce: h.nonce,
original_size: h.original_size,
})
}
_ => Err(PqfileError::UnsupportedVersion(version)),
}
}