loam/
common.rs

1// common.rs    Common stuff
2//
3// Copyright (c) 2021  Douglas P Lau
4//
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8/// Errors for reading or writing loam files
9#[derive(Debug, thiserror::Error)]
10pub enum Error {
11    /// I/O error
12    #[error("I/O {0}")]
13    Io(#[from] std::io::Error),
14
15    /// Bincode error
16    #[error("Bincode {0}")]
17    Bincode(#[from] Box<bincode::ErrorKind>),
18
19    /// Invalid Header
20    #[error("Invalid Header")]
21    InvalidHeader,
22
23    /// Invalid CRC
24    #[error("Invalid CRC")]
25    InvalidCrc(Id),
26
27    /// Invalid Checkpoint
28    #[error("Invalid Checkpoint")]
29    InvalidCheckpoint,
30
31    /// Invalid ID
32    #[error("Invalid ID")]
33    InvalidId(Id),
34}
35
36/// Result for reading or writing loam files
37pub type Result<T> = std::result::Result<T, Error>;
38
39/// File header
40pub const HEADER: &[u8; 8] = b"loam0000";
41
42/// Chunk Identifier
43#[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    /// Create a new Id
54    pub fn new(id: u64) -> Self {
55        Id(id)
56    }
57
58    /// Check if Id is valid
59    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}