Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch impls based on crate features for u8 as an example #101

Merged
merged 13 commits into from
Apr 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ keywords = ["crc", "crc16", "crc32", "crc64", "hash"]
categories = ["algorithms", "no-std"]
edition = "2018"

[features]
# use the "NoTable" implementation for the default Crc<uXXX> struct, using no additional memory for a lookup table.
# Takes predence over "bytewise-mem-limit" and "slice16-mem-limit"
no-table-mem-limit = []
# use the "Bytewise" implementation for the default Crc<uXXX> struct, using 256 entries of the respective width for a lookup table.
# Takes predence over "slice16-mem-limit" and is used if no feature is selected
bytewise-mem-limit = []
# use the "Slice16" implementation for the default Crc<uXXX> 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 = []

[dependencies]
crc-catalog = "2.1.0"

Expand Down
98 changes: 94 additions & 4 deletions src/crc128.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crc_catalog::Algorithm;

use crate::util::crc128;
use crc_catalog::Algorithm;

mod bytewise;
mod default;
Expand Down Expand Up @@ -170,10 +169,101 @@ const fn update_slice16(

#[cfg(test)]
mod test {
use crate::{Bytewise, Crc, NoTable, Slice16};
use crate::{Bytewise, Crc, Implementation, NoTable, Slice16};
use crc_catalog::{Algorithm, CRC_82_DARC};

/// Test this opitimized version against the well known implementation to ensure correctness
#[test]
fn default_table_size() {
const TABLE_SIZE: usize = core::mem::size_of::<<u128 as Implementation>::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() {
let data: &[&str] = &[
Expand Down
87 changes: 82 additions & 5 deletions src/crc128/default.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,62 @@
use crate::table::crc128_table;
use crate::{Algorithm, Crc, Digest};
use crate::crc128::{finalize, init};
use crate::{Algorithm, Crc, Digest, Implementation};

use super::{finalize, init, update_bytewise};
#[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<u128> {
pub const fn new(algorithm: &'static Algorithm<u128>) -> Self {
akhilles marked this conversation as resolved.
Show resolved Hide resolved
let table = crc128_table(algorithm.width, algorithm.poly, algorithm.refin);
#[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 }
}

Expand All @@ -16,7 +67,33 @@ impl Crc<u128> {
}

const fn update(&self, crc: u128, bytes: &[u8]) -> u128 {
update_bytewise(crc, self.algorithm.refin, &self.table, bytes)
#[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<u128> {
Expand Down
95 changes: 93 additions & 2 deletions src/crc16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,101 @@ const fn update_slice16(

#[cfg(test)]
mod test {
use crate::{Bytewise, Crc, NoTable, Slice16};
use crate::{Bytewise, Crc, Implementation, NoTable, Slice16};
use crc_catalog::{Algorithm, CRC_16_IBM_SDLC};

/// Test this opitimized version against the well known implementation to ensure correctness
#[test]
fn default_table_size() {
const TABLE_SIZE: usize = core::mem::size_of::<<u16 as Implementation>::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() {
let data: &[&str] = &[
Expand Down
Loading