1use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("I/O {0}")]
13 Io(#[from] std::io::Error),
14
15 #[error("Bincode {0}")]
17 Bincode(#[from] Box<bincode::ErrorKind>),
18
19 #[error("Invalid Header")]
21 InvalidHeader,
22
23 #[error("Invalid CRC")]
25 InvalidCrc(Id),
26
27 #[error("Invalid Checkpoint")]
29 InvalidCheckpoint,
30
31 #[error("Invalid ID")]
33 InvalidId(Id),
34}
35
36pub type Result<T> = std::result::Result<T, Error>;
38
39pub const HEADER: &[u8; 8] = b"loam0000";
41
42#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
44pub struct Id(u64);
45
46impl fmt::Display for Id {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 write!(f, "Id: {:?}", self.0)
49 }
50}
51
52impl Id {
53 pub fn new(id: u64) -> Self {
55 Id(id)
56 }
57
58 pub fn is_valid(self) -> bool {
60 self.0 > 0
61 }
62
63 pub(crate) fn from_le_bytes(bytes: [u8; 8]) -> Self {
64 Id(u64::from_le_bytes(bytes))
65 }
66
67 pub(crate) fn to_le_bytes(self) -> [u8; 8] {
68 self.0.to_le_bytes()
69 }
70
71 pub(crate) fn from_usize(id: usize) -> Self {
72 Id(id as u64)
73 }
74
75 pub(crate) fn to_usize(self) -> usize {
76 self.0 as usize
77 }
78}
79
80#[cfg(feature = "crc")]
81pub const CRC_SZ: usize = 4;
82
83#[cfg(feature = "crc")]
84pub fn checksum(buf: &[u8]) -> Option<u32> {
85 let mut hasher = crc32fast::Hasher::new();
86 hasher.update(&buf);
87 Some(hasher.finalize())
88}
89
90#[cfg(not(feature = "crc"))]
91pub const CRC_SZ: usize = 0;
92
93#[cfg(not(feature = "crc"))]
94pub fn checksum(_buf: &[u8]) -> Option<u32> {
95 None
96}