alopex_core/storage/
checksum.rs1use crate::storage::format::FormatError;
6use std::io::Read;
7
8#[repr(u8)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum ChecksumAlgorithm {
12 Crc32 = 0,
14 Xxh64 = 1,
16}
17
18pub fn compute(data: &[u8], algorithm: ChecksumAlgorithm) -> Result<u64, FormatError> {
20 match algorithm {
21 ChecksumAlgorithm::Crc32 => {
22 let mut hasher = crc32fast::Hasher::new();
23 hasher.update(data);
24 Ok(hasher.finalize() as u64)
25 }
26 ChecksumAlgorithm::Xxh64 => {
27 #[cfg(feature = "checksum-xxh64")]
28 {
29 let mut hasher = xxhash_rust::xxh64::Xxh64::new(0);
30 hasher.update(data);
31 Ok(hasher.digest())
32 }
33 #[cfg(not(feature = "checksum-xxh64"))]
34 {
35 Err(FormatError::UnsupportedChecksum {
36 algorithm: algorithm as u8,
37 })
38 }
39 }
40 }
41}
42
43pub fn compute_stream<R: Read>(
45 reader: &mut R,
46 algorithm: ChecksumAlgorithm,
47) -> Result<u64, FormatError> {
48 const BUF_SIZE: usize = 16 * 1024;
49 let mut buf = [0u8; BUF_SIZE];
50 match algorithm {
51 ChecksumAlgorithm::Crc32 => {
52 let mut hasher = crc32fast::Hasher::new();
53 loop {
54 let read = reader
55 .read(&mut buf)
56 .map_err(|_| FormatError::ChecksumMismatch {
57 expected: 0,
58 found: 0,
59 })?;
60 if read == 0 {
61 break;
62 }
63 hasher.update(&buf[..read]);
64 }
65 Ok(hasher.finalize() as u64)
66 }
67 ChecksumAlgorithm::Xxh64 => {
68 #[cfg(feature = "checksum-xxh64")]
69 {
70 let mut hasher = xxhash_rust::xxh64::Xxh64::new(0);
71 loop {
72 let read =
73 reader
74 .read(&mut buf)
75 .map_err(|_| FormatError::ChecksumMismatch {
76 expected: 0,
77 found: 0,
78 })?;
79 if read == 0 {
80 break;
81 }
82 hasher.update(&buf[..read]);
83 }
84 Ok(hasher.digest())
85 }
86 #[cfg(not(feature = "checksum-xxh64"))]
87 {
88 Err(FormatError::UnsupportedChecksum {
89 algorithm: algorithm as u8,
90 })
91 }
92 }
93 }
94}
95
96pub fn verify(data: &[u8], algorithm: ChecksumAlgorithm, expected: u64) -> Result<(), FormatError> {
98 let found = compute(data, algorithm)?;
99 if found == expected {
100 Ok(())
101 } else {
102 Err(FormatError::ChecksumMismatch { expected, found })
103 }
104}
105
106pub fn verify_stream<R: Read>(
108 reader: &mut R,
109 algorithm: ChecksumAlgorithm,
110 expected: u64,
111) -> Result<(), FormatError> {
112 let found = compute_stream(reader, algorithm)?;
113 if found == expected {
114 Ok(())
115 } else {
116 Err(FormatError::ChecksumMismatch { expected, found })
117 }
118}