use std::{
fs::{File, OpenOptions},
io::{BufWriter, Read, Seek, Write},
path::Path,
time::{SystemTime, UNIX_EPOCH},
};
use crate::jam::{JAM_SIGNATURE, JamError};
#[derive(Clone, Debug, Default)]
pub struct JhrHeaderInfo {
pub date_created: u32,
pub mod_counter: u32,
pub active_msgs: u32,
pub password_crc: u32,
pub base_msg_num: u32,
}
impl JhrHeaderInfo {
const JHR_USED_HEADER_SIZE: usize = 24;
pub const JHR_HEADER_SIZE: u64 = 1024;
pub fn load(file: &mut File) -> crate::Result<Self> {
let data = &mut [0; Self::JHR_USED_HEADER_SIZE];
file.read_exact(data)?;
if !data.starts_with(&JAM_SIGNATURE) {
return Err(JamError::InvalidHeaderSignature.into());
}
let mut data = &data[4..];
convert_u32!(datecreated, data);
convert_u32!(modcounter, data);
convert_u32!(activemsgs, data);
convert_u32!(passwordcrc, data);
convert_u32!(basemsgnum, data);
Ok(Self {
date_created: datecreated,
mod_counter: modcounter,
active_msgs: activemsgs,
password_crc: passwordcrc,
base_msg_num: basemsgnum,
})
}
pub(crate) fn create<P: AsRef<Path>>(file_name: &P, passwordcrc: u32) -> crate::Result<()> {
let now = SystemTime::now();
let unix_time = now.duration_since(UNIX_EPOCH)?;
let datecreated = unix_time.as_secs() as u32;
let mut result = Vec::with_capacity(Self::JHR_HEADER_SIZE as usize);
result.extend(JAM_SIGNATURE);
result.extend(&datecreated.to_le_bytes());
result.extend(&0u32.to_le_bytes());
result.extend(&0u32.to_le_bytes());
result.extend(&passwordcrc.to_le_bytes());
result.extend(&1u32.to_le_bytes());
result.resize(Self::JHR_HEADER_SIZE as usize, 0);
let mut file = OpenOptions::new()
.create_new(true)
.write(true)
.open(file_name)?;
file.write_all(&result)?;
Ok(())
}
pub(crate) fn update(&mut self, file: &mut BufWriter<File>) -> crate::Result<()> {
self.mod_counter = self.mod_counter.wrapping_add(1);
self.store(file)
}
pub(crate) fn store(&self, file: &mut BufWriter<File>) -> crate::Result<()> {
file.seek(std::io::SeekFrom::Start(8))?;
file.write_all(&self.mod_counter.to_le_bytes())?;
file.write_all(&self.active_msgs.to_le_bytes())?;
file.write_all(&self.password_crc.to_le_bytes())?;
file.write_all(&self.base_msg_num.to_le_bytes())?;
Ok(())
}
}