use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("I/O {0}")]
Io(#[from] std::io::Error),
#[error("Bincode {0}")]
Bincode(#[from] Box<bincode::ErrorKind>),
#[error("Invalid Header")]
InvalidHeader,
#[error("Invalid CRC")]
InvalidCrc(Id),
#[error("Invalid Checkpoint")]
InvalidCheckpoint,
#[error("Invalid ID")]
InvalidId(Id),
}
pub type Result<T> = std::result::Result<T, Error>;
pub const HEADER: &[u8; 8] = b"loam0000";
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct Id(u64);
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Id: {:?}", self.0)
}
}
impl Id {
pub fn new(id: u64) -> Self {
Id(id)
}
pub fn is_valid(self) -> bool {
self.0 > 0
}
pub(crate) fn from_le_bytes(bytes: [u8; 8]) -> Self {
Id(u64::from_le_bytes(bytes))
}
pub(crate) fn to_le_bytes(self) -> [u8; 8] {
self.0.to_le_bytes()
}
pub(crate) fn from_usize(id: usize) -> Self {
Id(id as u64)
}
pub(crate) fn to_usize(self) -> usize {
self.0 as usize
}
}
#[cfg(feature = "crc")]
pub const CRC_SZ: usize = 4;
#[cfg(feature = "crc")]
pub fn checksum(buf: &[u8]) -> Option<u32> {
let mut hasher = crc32fast::Hasher::new();
hasher.update(&buf);
Some(hasher.finalize())
}
#[cfg(not(feature = "crc"))]
pub const CRC_SZ: usize = 0;
#[cfg(not(feature = "crc"))]
pub fn checksum(_buf: &[u8]) -> Option<u32> {
None
}