From b2c638ce6cfdd4659b07b8f8ee52ada3ce43695e Mon Sep 17 00:00:00 2001 From: Akhil Velagapudi <4@4khil.com> Date: Sun, 10 Mar 2024 15:12:48 -0700 Subject: [PATCH] Add non-breaking API for custom implementations The previous attempt was a breaking change. Signed-off-by: Akhil Velagapudi <4@4khil.com> --- .github/workflows/ci.yaml | 2 +- Cargo.toml | 13 +- README.md | 24 ++-- benches/bench.rs | 30 ++--- src/crc128.rs | 100 +-------------- src/crc128/bytewise.rs | 19 +-- src/crc128/default.rs | 126 ------------------- src/crc128/nolookup.rs | 15 ++- src/crc128/slice16.rs | 18 +-- src/crc16.rs | 100 +-------------- src/crc16/bytewise.rs | 19 +-- src/crc16/default.rs | 126 ------------------- src/crc16/nolookup.rs | 14 +-- src/crc16/slice16.rs | 18 +-- src/crc32.rs | 100 +-------------- src/crc32/bytewise.rs | 19 +-- src/crc32/default.rs | 126 ------------------- src/crc32/nolookup.rs | 15 ++- src/crc32/slice16.rs | 18 +-- src/crc64.rs | 100 +-------------- src/crc64/bytewise.rs | 19 +-- src/crc64/default.rs | 126 ------------------- src/crc64/nolookup.rs | 15 ++- src/crc64/slice16.rs | 18 +-- src/crc8.rs | 100 +-------------- src/crc8/bytewise.rs | 19 +-- src/crc8/default.rs | 126 ------------------- src/crc8/nolookup.rs | 14 +-- src/crc8/slice16.rs | 18 +-- src/lib.rs | 57 ++++----- tests/test_under_all_feature_combinations.sh | 2 +- 31 files changed, 202 insertions(+), 1314 deletions(-) delete mode 100644 src/crc128/default.rs delete mode 100644 src/crc16/default.rs delete mode 100644 src/crc32/default.rs delete mode 100644 src/crc64/default.rs delete mode 100644 src/crc8/default.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e9597fb..a6889f4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: strategy: matrix: rust: - - 1.56.0 + - 1.65.0 - stable - beta steps: diff --git a/Cargo.toml b/Cargo.toml index 02d01f2..a1578a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,18 +13,7 @@ description = "Rust implementation of CRC with support of various standards" keywords = ["crc", "crc16", "crc32", "crc64", "hash"] categories = ["algorithms", "no-std"] edition = "2021" -rust-version = "1.56" - -# [features] -# use the "NoTable" implementation for the default Crc struct, using no additional memory for a lookup table. -# Takes precedence over "bytewise-mem-limit" and "slice16-mem-limit" -# no-table-mem-limit = [] -# use the "Bytewise" implementation for the default Crc struct, using 256 entries of the respective width for a lookup table. -# Takes precedence over "slice16-mem-limit" and is used if no feature is selected -# bytewise-mem-limit = [] -# use the "Slice16" implementation for the default Crc struct, using 256 * 16 entries of the respective width for a lookup table. -# Can be overriden by setting "bytewise-mem-limit" and "slice16-mem-limit" -# slice16-mem-limit = [] +rust-version = "1.65" [dependencies] crc-catalog = "2.4.0" diff --git a/README.md b/README.md index 2548e67..fed8ef3 100644 --- a/README.md +++ b/README.md @@ -43,29 +43,21 @@ assert_eq!(digest.finalize(), 0xaee7); ### Minimum supported Rust version (MSRV) -This crate's MSRV is 1.56. +This crate's MSRV is 1.65. At a minimum, the MSRV will be <= the oldest stable release in the last 12 months. MSRV may be bumped in minor version releases. -### Lookup table flavors +### Implementations -This crate offers three flavors of lookup tables providing a tradeoff between computation speed and used memory. -See the benchmark section for hints, but do benchmarks on your target hardware to decide if the tradeoff is worth it to you. +This crate has several pluggable implementations: -1. `NoTable` provides an implementation that uses no additional memory -2. `Bytewise` provides an implementation that uses a lookup table that uses 256 entries of the used width (e.g. for u32 thats 256 * 4 bytes) -3. `Slice16` provides an implementation that uses a lookup table that uses 16 * 256 entries of the used width (e.g. for u32 thats 16 * 256 * 4 bytes) +1. `NoTable` doesn't use a lookup table, and thus minimizes binary size and memory usage. +2. `Table<1>` uses a lookup table with 256 entries (e.g. for u32 thats 256 * 4 bytes). +3. `Table<16>` uses a lookup table with 16 * 256 entries (e.g. for u32 thats 16 * 256 * 4 bytes). -These can be used by substituting `Crc` with e.g. `Crc>`. The flavor for `Crc` is chosen based on three crate features: +`Table<1>` is the default implementation, but this can be overridden by specifying `I` in `Crc`. E.g.: `Crc`, `Crc>`, ... -* no-table-mem-limit: Takes precedence over "bytewise-mem-limit" or "slice16-mem-limit" -* bytewise-mem-limit: Takes precedence over "slice16-mem-limit" and can be overridden by setting "no-table-mem-limit" -* slice16-mem-limit: Can be overridden by setting "bytewise-mem-limit" or "no-table-mem-limit" - -If no feature is selected, the `Bytewise` flavor is used. - -Note that these tables can bloat your binary size if you precalculate them at compiletime (this happens in `Crc::new`). -Choosing a crate like oncecell or lazystatic to compute them once at runtime may be preferable where binary size is a concern. +NOTE: Lookup tables will increase binary size if they're generated at compile-time. Wrapping `Crc` initialization in a `std::cell::OnceCell` may be preferable if binary size is a concern. ### Benchmark diff --git a/benches/bench.rs b/benches/bench.rs index b3fa134..25d6bc3 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -2,26 +2,26 @@ use crc::*; use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; pub const BLUETOOTH: Crc = Crc::::new(&CRC_8_BLUETOOTH); -pub const BLUETOOTH_SLICE16: Crc> = Crc::>::new(&CRC_8_BLUETOOTH); -pub const BLUETOOTH_BYTEWISE: Crc> = Crc::>::new(&CRC_8_BLUETOOTH); -pub const BLUETOOTH_NOLOOKUP: Crc> = Crc::>::new(&CRC_8_BLUETOOTH); +pub const BLUETOOTH_SLICE16: Crc> = Crc::>::new(&CRC_8_BLUETOOTH); +pub const BLUETOOTH_BYTEWISE: Crc> = Crc::>::new(&CRC_8_BLUETOOTH); +pub const BLUETOOTH_NOLOOKUP: Crc = Crc::::new(&CRC_8_BLUETOOTH); pub const X25: Crc = Crc::::new(&CRC_16_IBM_SDLC); -pub const X25_SLICE16: Crc> = Crc::>::new(&CRC_16_IBM_SDLC); -pub const X25_BYTEWISE: Crc> = Crc::>::new(&CRC_16_IBM_SDLC); -pub const X25_NOLOOKUP: Crc> = Crc::>::new(&CRC_16_IBM_SDLC); +pub const X25_SLICE16: Crc> = Crc::>::new(&CRC_16_IBM_SDLC); +pub const X25_BYTEWISE: Crc> = Crc::>::new(&CRC_16_IBM_SDLC); +pub const X25_NOLOOKUP: Crc = Crc::::new(&CRC_16_IBM_SDLC); pub const ISCSI: Crc = Crc::::new(&CRC_32_ISCSI); -pub const ISCSI_SLICE16: Crc> = Crc::>::new(&CRC_32_ISCSI); -pub const ISCSI_BYTEWISE: Crc> = Crc::>::new(&CRC_32_ISCSI); -pub const ISCSI_NOLOOKUP: Crc> = Crc::>::new(&CRC_32_ISCSI); +pub const ISCSI_SLICE16: Crc> = Crc::>::new(&CRC_32_ISCSI); +pub const ISCSI_BYTEWISE: Crc> = Crc::>::new(&CRC_32_ISCSI); +pub const ISCSI_NOLOOKUP: Crc = Crc::::new(&CRC_32_ISCSI); pub const GSM_40: Crc = Crc::::new(&CRC_40_GSM); pub const ECMA: Crc = Crc::::new(&CRC_64_ECMA_182); -pub const ECMA_SLICE16: Crc> = Crc::>::new(&CRC_64_ECMA_182); -pub const ECMA_BYTEWISE: Crc> = Crc::>::new(&CRC_64_ECMA_182); -pub const ECMA_NOLOOKUP: Crc> = Crc::>::new(&CRC_64_ECMA_182); +pub const ECMA_SLICE16: Crc> = Crc::>::new(&CRC_64_ECMA_182); +pub const ECMA_BYTEWISE: Crc> = Crc::>::new(&CRC_64_ECMA_182); +pub const ECMA_NOLOOKUP: Crc = Crc::::new(&CRC_64_ECMA_182); pub const DARC: Crc = Crc::::new(&CRC_82_DARC); -pub const DARC_SLICE16: Crc> = Crc::>::new(&CRC_82_DARC); -pub const DARC_BYTEWISE: Crc> = Crc::>::new(&CRC_82_DARC); -pub const DARC_NOLOOKUP: Crc> = Crc::>::new(&CRC_82_DARC); +pub const DARC_SLICE16: Crc> = Crc::>::new(&CRC_82_DARC); +pub const DARC_BYTEWISE: Crc> = Crc::>::new(&CRC_82_DARC); +pub const DARC_NOLOOKUP: Crc = Crc::::new(&CRC_82_DARC); static KB: usize = 1024; diff --git a/src/crc128.rs b/src/crc128.rs index a380a0e..480061f 100644 --- a/src/crc128.rs +++ b/src/crc128.rs @@ -2,7 +2,6 @@ use crate::util::crc128; use crc_catalog::Algorithm; mod bytewise; -mod default; mod nolookup; mod slice16; @@ -169,100 +168,9 @@ const fn update_slice16( #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; + use crate::*; use crc_catalog::{Algorithm, CRC_82_DARC}; - #[test] - fn default_table_size() { - const TABLE_SIZE: usize = core::mem::size_of::<::Table>(); - const BYTES_PER_ENTRY: usize = 16; - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * 16 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - let _ = TABLE_SIZE; - let _ = BYTES_PER_ENTRY; - } - /// Test this optimized version against the well known implementation to ensure correctness #[test] fn correctness() { @@ -291,9 +199,9 @@ mod test { for alg in algs_to_test { for data in data { - let crc_slice16 = Crc::>::new(alg); - let crc_nolookup = Crc::>::new(alg); - let expected = Crc::>::new(alg).checksum(data.as_bytes()); + let crc_slice16 = Crc::>::new(alg); + let crc_nolookup = Crc::::new(alg); + let expected = Crc::>::new(alg).checksum(data.as_bytes()); // Check that doing all at once works as expected assert_eq!(crc_slice16.checksum(data.as_bytes()), expected); diff --git a/src/crc128/bytewise.rs b/src/crc128/bytewise.rs index 500d7ea..27d80fe 100644 --- a/src/crc128/bytewise.rs +++ b/src/crc128/bytewise.rs @@ -1,12 +1,15 @@ use crate::table::crc128_table; -use crate::{Algorithm, Bytewise, Crc, Digest}; +use crate::*; use super::{finalize, init, update_bytewise}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { let table = crc128_table(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + Self { + algorithm, + data: [table], + } } pub const fn checksum(&self, bytes: &[u8]) -> u128 { @@ -16,10 +19,10 @@ impl Crc> { } const fn update(&self, crc: u128, bytes: &[u8]) -> u128 { - update_bytewise(crc, self.algorithm.refin, &self.table, bytes) + update_bytewise(crc, self.algorithm.refin, &self.data[0], bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +31,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u128) -> Digest> { + pub const fn digest_with_initial(&self, initial: u128) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Bytewise> { - const fn new(crc: &'a Crc>, value: u128) -> Self { +impl<'a> Digest<'a, u128, Table<1>> { + const fn new(crc: &'a Crc>, value: u128) -> Self { Digest { crc, value } } diff --git a/src/crc128/default.rs b/src/crc128/default.rs deleted file mode 100644 index d623ac4..0000000 --- a/src/crc128/default.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::crc128::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u128 { - type Width = u128; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u128 { - type Width = u128; - type Table = [u128; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u128 { - type Width = u128; - type Table = [[u128; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u128 { - type Width = u128; - type Table = [u128; 256]; -} - -impl Crc { - pub const fn new(algorithm: &'static Algorithm) -> Self { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - let table = - crate::table::crc128_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc128_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - let table = crate::table::crc128_table(algorithm.width, algorithm.poly, algorithm.refin); - - Self { algorithm, table } - } - - pub const fn checksum(&self, bytes: &[u8]) -> u128 { - let mut crc = init(self.algorithm, self.algorithm.init); - crc = self.update(crc, bytes); - finalize(self.algorithm, crc) - } - - const fn update(&self, crc: u128, bytes: &[u8]) -> u128 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - } - - pub const fn digest(&self) -> Digest { - self.digest_with_initial(self.algorithm.init) - } - - /// Construct a `Digest` with a given initial value. - /// - /// This overrides the initial value specified by the algorithm. - /// The effects of the algorithm's properties `refin` and `width` - /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u128) -> Digest { - let value = init(self.algorithm, initial); - Digest::new(self, value) - } -} - -impl<'a> Digest<'a, u128> { - const fn new(crc: &'a Crc, value: u128) -> Self { - Digest { crc, value } - } - - pub fn update(&mut self, bytes: &[u8]) { - self.value = self.crc.update(self.value, bytes); - } - - pub const fn finalize(self) -> u128 { - finalize(self.crc.algorithm, self.value) - } -} diff --git a/src/crc128/nolookup.rs b/src/crc128/nolookup.rs index ef22e3b..fa73951 100644 --- a/src/crc128/nolookup.rs +++ b/src/crc128/nolookup.rs @@ -1,12 +1,11 @@ -use crate::{Algorithm, Crc, Digest, NoTable}; - use super::{finalize, init, update_nolookup}; +use crate::*; -impl Crc> { +impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { Self { algorithm, - table: (), + data: [], } } @@ -20,7 +19,7 @@ impl Crc> { update_nolookup(crc, self.algorithm, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest { self.digest_with_initial(self.algorithm.init) } @@ -29,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u128) -> Digest> { + pub const fn digest_with_initial(&self, initial: u128) -> Digest { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, NoTable> { - const fn new(crc: &'a Crc>, value: u128) -> Self { +impl<'a> Digest<'a, u128, NoTable> { + const fn new(crc: &'a Crc, value: u128) -> Self { Digest { crc, value } } diff --git a/src/crc128/slice16.rs b/src/crc128/slice16.rs index 948a70d..7d845fd 100644 --- a/src/crc128/slice16.rs +++ b/src/crc128/slice16.rs @@ -1,12 +1,12 @@ use crate::table::crc128_table_slice_16; -use crate::{Algorithm, Crc, Digest, Slice16}; +use crate::{Algorithm, Crc, Digest, Table}; use super::{finalize, init, update_slice16}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { - let table = crc128_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + let data = crc128_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); + Self { algorithm, data } } pub const fn checksum(&self, bytes: &[u8]) -> u128 { @@ -16,10 +16,10 @@ impl Crc> { } const fn update(&self, crc: u128, bytes: &[u8]) -> u128 { - update_slice16(crc, self.algorithm.refin, &self.table, bytes) + update_slice16(crc, self.algorithm.refin, &self.data, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u128) -> Digest> { + pub const fn digest_with_initial(&self, initial: u128) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Slice16> { - const fn new(crc: &'a Crc>, value: u128) -> Self { +impl<'a> Digest<'a, u128, Table<16>> { + const fn new(crc: &'a Crc>, value: u128) -> Self { Digest { crc, value } } diff --git a/src/crc16.rs b/src/crc16.rs index 9001f2f..392cd81 100644 --- a/src/crc16.rs +++ b/src/crc16.rs @@ -2,7 +2,6 @@ use crate::util::crc16; use crc_catalog::Algorithm; mod bytewise; -mod default; mod nolookup; mod slice16; @@ -141,100 +140,9 @@ const fn update_slice16( #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; + use crate::*; use crc_catalog::{Algorithm, CRC_16_IBM_SDLC}; - #[test] - fn default_table_size() { - const TABLE_SIZE: usize = core::mem::size_of::<::Table>(); - const BYTES_PER_ENTRY: usize = 2; - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * 16 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - let _ = TABLE_SIZE; - let _ = BYTES_PER_ENTRY; - } - /// Test this optimized version against the well known implementation to ensure correctness #[test] fn correctness() { @@ -263,9 +171,9 @@ mod test { for alg in algs_to_test { for data in data { - let crc_slice16 = Crc::>::new(alg); - let crc_nolookup = Crc::>::new(alg); - let expected = Crc::>::new(alg).checksum(data.as_bytes()); + let crc_slice16 = Crc::>::new(alg); + let crc_nolookup = Crc::::new(alg); + let expected = Crc::>::new(alg).checksum(data.as_bytes()); // Check that doing all at once works as expected assert_eq!(crc_slice16.checksum(data.as_bytes()), expected); diff --git a/src/crc16/bytewise.rs b/src/crc16/bytewise.rs index 1f042dd..85fe830 100644 --- a/src/crc16/bytewise.rs +++ b/src/crc16/bytewise.rs @@ -1,11 +1,14 @@ use crate::crc16::{finalize, init, update_bytewise}; use crate::table::crc16_table; -use crate::{Algorithm, Bytewise, Crc, Digest}; +use crate::*; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { let table = crc16_table(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + Self { + algorithm, + data: [table], + } } pub const fn checksum(&self, bytes: &[u8]) -> u16 { @@ -15,10 +18,10 @@ impl Crc> { } const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { - update_bytewise(crc, self.algorithm.refin, &self.table, bytes) + update_bytewise(crc, self.algorithm.refin, &self.data[0], bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -27,14 +30,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u16) -> Digest> { + pub const fn digest_with_initial(&self, initial: u16) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Bytewise> { - const fn new(crc: &'a Crc>, value: u16) -> Self { +impl<'a> Digest<'a, u16, Table<1>> { + const fn new(crc: &'a Crc>, value: u16) -> Self { Digest { crc, value } } diff --git a/src/crc16/default.rs b/src/crc16/default.rs deleted file mode 100644 index 55b72c9..0000000 --- a/src/crc16/default.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::crc16::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u16 { - type Width = u16; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u16 { - type Width = u16; - type Table = [u16; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u16 { - type Width = u16; - type Table = [[u16; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u16 { - type Width = u16; - type Table = [u16; 256]; -} - -impl Crc { - pub const fn new(algorithm: &'static Algorithm) -> Self { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - let table = - crate::table::crc16_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc16_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - let table = crate::table::crc16_table(algorithm.width, algorithm.poly, algorithm.refin); - - Self { algorithm, table } - } - - pub const fn checksum(&self, bytes: &[u8]) -> u16 { - let mut crc = init(self.algorithm, self.algorithm.init); - crc = self.update(crc, bytes); - finalize(self.algorithm, crc) - } - - const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - } - - pub const fn digest(&self) -> Digest { - self.digest_with_initial(self.algorithm.init) - } - - /// Construct a `Digest` with a given initial value. - /// - /// This overrides the initial value specified by the algorithm. - /// The effects of the algorithm's properties `refin` and `width` - /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u16) -> Digest { - let value = init(self.algorithm, initial); - Digest::new(self, value) - } -} - -impl<'a> Digest<'a, u16> { - const fn new(crc: &'a Crc, value: u16) -> Self { - Digest { crc, value } - } - - pub fn update(&mut self, bytes: &[u8]) { - self.value = self.crc.update(self.value, bytes); - } - - pub const fn finalize(self) -> u16 { - finalize(self.crc.algorithm, self.value) - } -} diff --git a/src/crc16/nolookup.rs b/src/crc16/nolookup.rs index eedf5a2..7b1f6c5 100644 --- a/src/crc16/nolookup.rs +++ b/src/crc16/nolookup.rs @@ -1,11 +1,11 @@ use crate::crc16::{finalize, init, update_nolookup}; -use crate::{Algorithm, Crc, Digest, NoTable}; +use crate::*; -impl Crc> { +impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { Self { algorithm, - table: (), + data: [], } } @@ -19,7 +19,7 @@ impl Crc> { update_nolookup(crc, self.algorithm, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u16) -> Digest> { + pub const fn digest_with_initial(&self, initial: u16) -> Digest { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, NoTable> { - const fn new(crc: &'a Crc>, value: u16) -> Self { +impl<'a> Digest<'a, u16, NoTable> { + const fn new(crc: &'a Crc, value: u16) -> Self { Digest { crc, value } } diff --git a/src/crc16/slice16.rs b/src/crc16/slice16.rs index 781cff4..7b855fa 100644 --- a/src/crc16/slice16.rs +++ b/src/crc16/slice16.rs @@ -1,11 +1,11 @@ use crate::crc16::{finalize, init, update_slice16}; use crate::table::crc16_table_slice_16; -use crate::{Algorithm, Crc, Digest, Slice16}; +use crate::{Algorithm, Crc, Digest, Table}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { - let table = crc16_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + let data = crc16_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); + Self { algorithm, data } } pub const fn checksum(&self, bytes: &[u8]) -> u16 { @@ -15,10 +15,10 @@ impl Crc> { } const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { - update_slice16(crc, self.algorithm.refin, &self.table, bytes) + update_slice16(crc, self.algorithm.refin, &self.data, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -27,14 +27,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u16) -> Digest> { + pub const fn digest_with_initial(&self, initial: u16) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Slice16> { - const fn new(crc: &'a Crc>, value: u16) -> Self { +impl<'a> Digest<'a, u16, Table<16>> { + const fn new(crc: &'a Crc>, value: u16) -> Self { Digest { crc, value } } diff --git a/src/crc32.rs b/src/crc32.rs index 0467533..4385685 100644 --- a/src/crc32.rs +++ b/src/crc32.rs @@ -2,7 +2,6 @@ use crate::util::crc32; use crc_catalog::Algorithm; mod bytewise; -mod default; mod nolookup; mod slice16; @@ -152,100 +151,9 @@ const fn update_slice16( #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; + use crate::*; use crc_catalog::{Algorithm, CRC_32_ISCSI}; - #[test] - fn default_table_size() { - const TABLE_SIZE: usize = core::mem::size_of::<::Table>(); - const BYTES_PER_ENTRY: usize = 4; - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * 16 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - let _ = TABLE_SIZE; - let _ = BYTES_PER_ENTRY; - } - /// Test this optimized version against the well known implementation to ensure correctness #[test] fn correctness() { @@ -275,9 +183,9 @@ mod test { for alg in algs_to_test { for data in data { - let crc_slice16 = Crc::>::new(alg); - let crc_nolookup = Crc::>::new(alg); - let expected = Crc::>::new(alg).checksum(data.as_bytes()); + let crc_slice16 = Crc::>::new(alg); + let crc_nolookup = Crc::::new(alg); + let expected = Crc::>::new(alg).checksum(data.as_bytes()); // Check that doing all at once works as expected assert_eq!(crc_slice16.checksum(data.as_bytes()), expected); diff --git a/src/crc32/bytewise.rs b/src/crc32/bytewise.rs index 88c7976..586631c 100644 --- a/src/crc32/bytewise.rs +++ b/src/crc32/bytewise.rs @@ -1,12 +1,15 @@ use crate::table::crc32_table; -use crate::{Algorithm, Bytewise, Crc, Digest}; +use crate::*; use crate::crc32::{finalize, init, update_bytewise}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { let table = crc32_table(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + Self { + algorithm, + data: [table], + } } pub const fn checksum(&self, bytes: &[u8]) -> u32 { @@ -16,10 +19,10 @@ impl Crc> { } const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { - update_bytewise(crc, self.algorithm.refin, &self.table, bytes) + update_bytewise(crc, self.algorithm.refin, &self.data[0], bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +31,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u32) -> Digest> { + pub const fn digest_with_initial(&self, initial: u32) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Bytewise> { - const fn new(crc: &'a Crc>, value: u32) -> Self { +impl<'a> Digest<'a, u32, Table<1>> { + const fn new(crc: &'a Crc>, value: u32) -> Self { Digest { crc, value } } diff --git a/src/crc32/default.rs b/src/crc32/default.rs deleted file mode 100644 index 0aaedd3..0000000 --- a/src/crc32/default.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::crc32::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u32 { - type Width = u32; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u32 { - type Width = u32; - type Table = [u32; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u32 { - type Width = u32; - type Table = [[u32; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u32 { - type Width = u32; - type Table = [u32; 256]; -} - -impl Crc { - pub const fn new(algorithm: &'static Algorithm) -> Self { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - let table = - crate::table::crc32_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc32_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - let table = crate::table::crc32_table(algorithm.width, algorithm.poly, algorithm.refin); - - Self { algorithm, table } - } - - pub const fn checksum(&self, bytes: &[u8]) -> u32 { - let mut crc = init(self.algorithm, self.algorithm.init); - crc = self.update(crc, bytes); - finalize(self.algorithm, crc) - } - - const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - } - - pub const fn digest(&self) -> Digest { - self.digest_with_initial(self.algorithm.init) - } - - /// Construct a `Digest` with a given initial value. - /// - /// This overrides the initial value specified by the algorithm. - /// The effects of the algorithm's properties `refin` and `width` - /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u32) -> Digest { - let value = init(self.algorithm, initial); - Digest::new(self, value) - } -} - -impl<'a> Digest<'a, u32> { - const fn new(crc: &'a Crc, value: u32) -> Self { - Digest { crc, value } - } - - pub fn update(&mut self, bytes: &[u8]) { - self.value = self.crc.update(self.value, bytes); - } - - pub const fn finalize(self) -> u32 { - finalize(self.crc.algorithm, self.value) - } -} diff --git a/src/crc32/nolookup.rs b/src/crc32/nolookup.rs index de40987..b44959e 100644 --- a/src/crc32/nolookup.rs +++ b/src/crc32/nolookup.rs @@ -1,12 +1,11 @@ -use crate::{Algorithm, Crc, Digest, NoTable}; - use super::{finalize, init, update_nolookup}; +use crate::*; -impl Crc> { +impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { Self { algorithm, - table: (), + data: [], } } @@ -20,7 +19,7 @@ impl Crc> { update_nolookup(crc, self.algorithm, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest { self.digest_with_initial(self.algorithm.init) } @@ -29,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u32) -> Digest> { + pub const fn digest_with_initial(&self, initial: u32) -> Digest { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, NoTable> { - const fn new(crc: &'a Crc>, value: u32) -> Self { +impl<'a> Digest<'a, u32, NoTable> { + const fn new(crc: &'a Crc, value: u32) -> Self { Digest { crc, value } } diff --git a/src/crc32/slice16.rs b/src/crc32/slice16.rs index 638becc..cd4a139 100644 --- a/src/crc32/slice16.rs +++ b/src/crc32/slice16.rs @@ -1,12 +1,12 @@ use crate::table::crc32_table_slice_16; -use crate::{Algorithm, Crc, Digest, Slice16}; +use crate::{Algorithm, Crc, Digest, Table}; use super::{finalize, init, update_slice16}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { - let table = crc32_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + let data = crc32_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); + Self { algorithm, data } } pub const fn checksum(&self, bytes: &[u8]) -> u32 { @@ -16,10 +16,10 @@ impl Crc> { } const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { - update_slice16(crc, self.algorithm.refin, &self.table, bytes) + update_slice16(crc, self.algorithm.refin, &self.data, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u32) -> Digest> { + pub const fn digest_with_initial(&self, initial: u32) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Slice16> { - const fn new(crc: &'a Crc>, value: u32) -> Self { +impl<'a> Digest<'a, u32, Table<16>> { + const fn new(crc: &'a Crc>, value: u32) -> Self { Digest { crc, value } } diff --git a/src/crc64.rs b/src/crc64.rs index 9abafd2..6793453 100644 --- a/src/crc64.rs +++ b/src/crc64.rs @@ -2,7 +2,6 @@ use crate::util::crc64; use crc_catalog::Algorithm; mod bytewise; -mod default; mod nolookup; mod slice16; @@ -154,100 +153,9 @@ const fn update_slice16( #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; + use crate::*; use crc_catalog::{Algorithm, CRC_64_ECMA_182}; - #[test] - fn default_table_size() { - const TABLE_SIZE: usize = core::mem::size_of::<::Table>(); - const BYTES_PER_ENTRY: usize = 8; - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * 16 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - let _ = TABLE_SIZE; - let _ = BYTES_PER_ENTRY; - } - /// Test this optimized version against the well known implementation to ensure correctness #[test] fn correctness() { @@ -276,9 +184,9 @@ mod test { for alg in algs_to_test { for data in data { - let crc_slice16 = Crc::>::new(alg); - let crc_nolookup = Crc::>::new(alg); - let expected = Crc::>::new(alg).checksum(data.as_bytes()); + let crc_slice16 = Crc::>::new(alg); + let crc_nolookup = Crc::::new(alg); + let expected = Crc::>::new(alg).checksum(data.as_bytes()); // Check that doing all at once works as expected assert_eq!(crc_slice16.checksum(data.as_bytes()), expected); diff --git a/src/crc64/bytewise.rs b/src/crc64/bytewise.rs index e4b66c0..50adb56 100644 --- a/src/crc64/bytewise.rs +++ b/src/crc64/bytewise.rs @@ -1,12 +1,15 @@ use crate::table::crc64_table; -use crate::{Algorithm, Bytewise, Crc, Digest}; +use crate::*; use super::{finalize, init, update_bytewise}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { let table = crc64_table(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + Self { + algorithm, + data: [table], + } } pub const fn checksum(&self, bytes: &[u8]) -> u64 { @@ -16,10 +19,10 @@ impl Crc> { } const fn update(&self, crc: u64, bytes: &[u8]) -> u64 { - update_bytewise(crc, self.algorithm.refin, &self.table, bytes) + update_bytewise(crc, self.algorithm.refin, &self.data[0], bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +31,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u64) -> Digest> { + pub const fn digest_with_initial(&self, initial: u64) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Bytewise> { - const fn new(crc: &'a Crc>, value: u64) -> Self { +impl<'a> Digest<'a, u64, Table<1>> { + const fn new(crc: &'a Crc>, value: u64) -> Self { Digest { crc, value } } diff --git a/src/crc64/default.rs b/src/crc64/default.rs deleted file mode 100644 index bf41dc8..0000000 --- a/src/crc64/default.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::crc64::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u64 { - type Width = u64; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u64 { - type Width = u64; - type Table = [u64; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u64 { - type Width = u64; - type Table = [[u64; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u64 { - type Width = u64; - type Table = [u64; 256]; -} - -impl Crc { - pub const fn new(algorithm: &'static Algorithm) -> Self { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - let table = - crate::table::crc64_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc64_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - let table = crate::table::crc64_table(algorithm.width, algorithm.poly, algorithm.refin); - - Self { algorithm, table } - } - - pub const fn checksum(&self, bytes: &[u8]) -> u64 { - let mut crc = init(self.algorithm, self.algorithm.init); - crc = self.update(crc, bytes); - finalize(self.algorithm, crc) - } - - const fn update(&self, crc: u64, bytes: &[u8]) -> u64 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - } - - pub const fn digest(&self) -> Digest { - self.digest_with_initial(self.algorithm.init) - } - - /// Construct a `Digest` with a given initial value. - /// - /// This overrides the initial value specified by the algorithm. - /// The effects of the algorithm's properties `refin` and `width` - /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u64) -> Digest { - let value = init(self.algorithm, initial); - Digest::new(self, value) - } -} - -impl<'a> Digest<'a, u64> { - const fn new(crc: &'a Crc, value: u64) -> Self { - Digest { crc, value } - } - - pub fn update(&mut self, bytes: &[u8]) { - self.value = self.crc.update(self.value, bytes); - } - - pub const fn finalize(self) -> u64 { - finalize(self.crc.algorithm, self.value) - } -} diff --git a/src/crc64/nolookup.rs b/src/crc64/nolookup.rs index 47ccc2c..01fc6bf 100644 --- a/src/crc64/nolookup.rs +++ b/src/crc64/nolookup.rs @@ -1,12 +1,11 @@ -use crate::{Algorithm, Crc, Digest, NoTable}; - use super::{finalize, init, update_nolookup}; +use crate::*; -impl Crc> { +impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { Self { algorithm, - table: (), + data: [], } } @@ -20,7 +19,7 @@ impl Crc> { update_nolookup(crc, self.algorithm, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest { self.digest_with_initial(self.algorithm.init) } @@ -29,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u64) -> Digest> { + pub const fn digest_with_initial(&self, initial: u64) -> Digest { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, NoTable> { - const fn new(crc: &'a Crc>, value: u64) -> Self { +impl<'a> Digest<'a, u64, NoTable> { + const fn new(crc: &'a Crc, value: u64) -> Self { Digest { crc, value } } diff --git a/src/crc64/slice16.rs b/src/crc64/slice16.rs index 0bd279e..e14ba1d 100644 --- a/src/crc64/slice16.rs +++ b/src/crc64/slice16.rs @@ -1,12 +1,12 @@ use crate::table::crc64_table_slice_16; -use crate::{Algorithm, Crc, Digest, Slice16}; +use crate::{Algorithm, Crc, Digest, Table}; use super::{finalize, init, update_slice16}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { - let table = crc64_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + let data = crc64_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); + Self { algorithm, data } } pub const fn checksum(&self, bytes: &[u8]) -> u64 { @@ -16,10 +16,10 @@ impl Crc> { } const fn update(&self, crc: u64, bytes: &[u8]) -> u64 { - update_slice16(crc, self.algorithm.refin, &self.table, bytes) + update_slice16(crc, self.algorithm.refin, &self.data, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u64) -> Digest> { + pub const fn digest_with_initial(&self, initial: u64) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Slice16> { - const fn new(crc: &'a Crc>, value: u64) -> Self { +impl<'a> Digest<'a, u64, Table<16>> { + const fn new(crc: &'a Crc>, value: u64) -> Self { Digest { crc, value } } diff --git a/src/crc8.rs b/src/crc8.rs index d33d906..9e38289 100644 --- a/src/crc8.rs +++ b/src/crc8.rs @@ -2,7 +2,6 @@ use crate::util::crc8; use crc_catalog::Algorithm; mod bytewise; -mod default; mod nolookup; mod slice16; @@ -88,100 +87,9 @@ const fn update_slice16(mut crc: u8, table: &[[u8; 256]; 16], bytes: &[u8]) -> u #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; + use crate::*; use crc_catalog::{Algorithm, CRC_8_BLUETOOTH}; - #[test] - fn default_table_size() { - const TABLE_SIZE: usize = core::mem::size_of::<::Table>(); - const BYTES_PER_ENTRY: usize = 1; - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - feature = "no-table-mem-limit", - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 0; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - #[cfg(all( - not(feature = "no-table-mem-limit"), - feature = "bytewise-mem-limit", - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - const EXPECTED: usize = 256 * 16 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - const EXPECTED: usize = 256 * BYTES_PER_ENTRY; - let _ = EXPECTED; - const _: () = assert!(EXPECTED == TABLE_SIZE); - } - let _ = TABLE_SIZE; - let _ = BYTES_PER_ENTRY; - } - /// Test this optimized version against the well known implementation to ensure correctness #[test] fn correctness() { @@ -210,9 +118,9 @@ mod test { for alg in algs_to_test { for data in data { - let crc_slice16 = Crc::>::new(alg); - let crc_nolookup = Crc::>::new(alg); - let expected = Crc::>::new(alg).checksum(data.as_bytes()); + let crc_slice16 = Crc::>::new(alg); + let crc_nolookup = Crc::::new(alg); + let expected = Crc::>::new(alg).checksum(data.as_bytes()); // Check that doing all at once works as expected assert_eq!(crc_slice16.checksum(data.as_bytes()), expected); diff --git a/src/crc8/bytewise.rs b/src/crc8/bytewise.rs index 1cae39e..ca30f99 100644 --- a/src/crc8/bytewise.rs +++ b/src/crc8/bytewise.rs @@ -1,11 +1,14 @@ use crate::crc8::{finalize, init, update_bytewise}; use crate::table::crc8_table; -use crate::{Algorithm, Bytewise, Crc, Digest}; +use crate::*; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { let table = crc8_table(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + Self { + algorithm, + data: [table], + } } pub const fn checksum(&self, bytes: &[u8]) -> u8 { @@ -15,10 +18,10 @@ impl Crc> { } const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { - update_bytewise(crc, &self.table, bytes) + update_bytewise(crc, &self.data[0], bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -27,14 +30,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u8) -> Digest> { + pub const fn digest_with_initial(&self, initial: u8) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Bytewise> { - const fn new(crc: &'a Crc>, value: u8) -> Self { +impl<'a> Digest<'a, u8, Table<1>> { + const fn new(crc: &'a Crc>, value: u8) -> Self { Digest { crc, value } } diff --git a/src/crc8/default.rs b/src/crc8/default.rs deleted file mode 100644 index 9923b3a..0000000 --- a/src/crc8/default.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::crc8::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u8 { - type Width = u8; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u8 { - type Width = u8; - type Table = [u8; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u8 { - type Width = u8; - type Table = [[u8; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u8 { - type Width = u8; - type Table = [u8; 256]; -} - -impl Crc { - pub const fn new(algorithm: &'static Algorithm) -> Self { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - let table = - crate::table::crc8_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc8_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - let table = crate::table::crc8_table(algorithm.width, algorithm.poly, algorithm.refin); - - Self { algorithm, table } - } - - pub const fn checksum(&self, bytes: &[u8]) -> u8 { - let mut crc = init(self.algorithm, self.algorithm.init); - crc = self.update(crc, bytes); - finalize(self.algorithm, crc) - } - - const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, &self.table, bytes) - } - } - - pub const fn digest(&self) -> Digest { - self.digest_with_initial(self.algorithm.init) - } - - /// Construct a `Digest` with a given initial value. - /// - /// This overrides the initial value specified by the algorithm. - /// The effects of the algorithm's properties `refin` and `width` - /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u8) -> Digest { - let value = init(self.algorithm, initial); - Digest::new(self, value) - } -} - -impl<'a> Digest<'a, u8> { - const fn new(crc: &'a Crc, value: u8) -> Self { - Digest { crc, value } - } - - pub fn update(&mut self, bytes: &[u8]) { - self.value = self.crc.update(self.value, bytes); - } - - pub const fn finalize(self) -> u8 { - finalize(self.crc.algorithm, self.value) - } -} diff --git a/src/crc8/nolookup.rs b/src/crc8/nolookup.rs index 4b19340..dd7971c 100644 --- a/src/crc8/nolookup.rs +++ b/src/crc8/nolookup.rs @@ -1,11 +1,11 @@ use crate::crc8::{finalize, init, update_nolookup}; -use crate::{Algorithm, Crc, Digest, NoTable}; +use crate::*; -impl Crc> { +impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { Self { algorithm, - table: (), + data: [], } } @@ -19,7 +19,7 @@ impl Crc> { update_nolookup(crc, self.algorithm, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest { self.digest_with_initial(self.algorithm.init) } @@ -28,14 +28,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u8) -> Digest> { + pub const fn digest_with_initial(&self, initial: u8) -> Digest { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, NoTable> { - const fn new(crc: &'a Crc>, value: u8) -> Self { +impl<'a> Digest<'a, u8, NoTable> { + const fn new(crc: &'a Crc, value: u8) -> Self { Digest { crc, value } } diff --git a/src/crc8/slice16.rs b/src/crc8/slice16.rs index a63ed84..1c820e0 100644 --- a/src/crc8/slice16.rs +++ b/src/crc8/slice16.rs @@ -1,11 +1,11 @@ use crate::crc8::{finalize, init, update_slice16}; use crate::table::crc8_table_slice_16; -use crate::{Algorithm, Crc, Digest, Slice16}; +use crate::{Algorithm, Crc, Digest, Table}; -impl Crc> { +impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { - let table = crc8_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - Self { algorithm, table } + let data = crc8_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); + Self { algorithm, data } } pub const fn checksum(&self, bytes: &[u8]) -> u8 { @@ -15,10 +15,10 @@ impl Crc> { } const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { - update_slice16(crc, &self.table, bytes) + update_slice16(crc, &self.data, bytes) } - pub const fn digest(&self) -> Digest> { + pub const fn digest(&self) -> Digest> { self.digest_with_initial(self.algorithm.init) } @@ -27,14 +27,14 @@ impl Crc> { /// This overrides the initial value specified by the algorithm. /// The effects of the algorithm's properties `refin` and `width` /// are applied to the custom initial value. - pub const fn digest_with_initial(&self, initial: u8) -> Digest> { + pub const fn digest_with_initial(&self, initial: u8) -> Digest> { let value = init(self.algorithm, initial); Digest::new(self, value) } } -impl<'a> Digest<'a, Slice16> { - const fn new(crc: &'a Crc>, value: u8) -> Self { +impl<'a> Digest<'a, u8, Table<16>> { + const fn new(crc: &'a Crc>, value: u8) -> Self { Digest { crc, value } } diff --git a/src/lib.rs b/src/lib.rs index 024e799..20549e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,53 +39,38 @@ mod crc8; mod table; mod util; -/// Implementation using a 16 * 256 entry lookup table. Use it with `Crc>` -pub struct Slice16(core::marker::PhantomData); +/// A trait for CRC implementations. +pub trait Implementation: private::Sealed { + /// Associated data necessary for the implementation (e.g. lookup tables). + type Data; +} -/// Implementation using a 256 entry lookup table. Use it with `Crc>` -pub struct Bytewise(core::marker::PhantomData); +/// A table-based implementation of the CRC algorithm, with `L` lanes. +/// The number of entries in the lookup table is `L * 256`. +pub struct Table {} -/// Implementation using no lookup table. Use it with `Crc>` -pub struct NoTable(core::marker::PhantomData); +/// An implementation of the CRC algorithm with no lookup table. +pub type NoTable = Table<0>; -impl crate::private::Sealed for Slice16 {} -impl crate::private::Sealed for Bytewise {} -impl crate::private::Sealed for NoTable {} +type DefaultImpl = Table<1>; -impl crate::Implementation for Slice16 { - type Width = W; - type Table = [[W; 256]; 16]; -} - -impl crate::Implementation for Bytewise { - type Width = W; - type Table = [W; 256]; -} - -impl crate::Implementation for NoTable { - type Width = W; - type Table = (); +impl Implementation for Table { + type Data = [[W; 256]; L]; } mod private { pub trait Sealed {} - impl Sealed for W {} -} - -pub trait Implementation: private::Sealed { - type Width: Width; - type Table; + impl Sealed for super::Table {} } -/// Crc with pluggable implementations ([NoTable], [Bytewise], [Slice16]). -/// To choose the default implementation, use the [Width] directly (e.g. `Crc`). -pub struct Crc { - pub algorithm: &'static Algorithm, - table: I::Table, +/// Crc instance with a specific width, algorithm, and implementation. +pub struct Crc { + pub algorithm: &'static Algorithm, + data: I::Data, } #[derive(Clone)] -pub struct Digest<'a, I: Implementation> { - crc: &'a Crc, - value: I::Width, +pub struct Digest<'a, W: Width, I: Implementation = DefaultImpl> { + crc: &'a Crc, + value: W, } diff --git a/tests/test_under_all_feature_combinations.sh b/tests/test_under_all_feature_combinations.sh index 2b44c73..76338cb 100755 --- a/tests/test_under_all_feature_combinations.sh +++ b/tests/test_under_all_feature_combinations.sh @@ -1,4 +1,4 @@ -set -ex +#!/bin/sh -ex cargo test cargo test --no-default-features