Skip to content

Commit

Permalink
Merge pull request #63 from paunstefan/crc8_support
Browse files Browse the repository at this point in the history
Added CRC8 support
  • Loading branch information
akhilles committed Aug 5, 2021
2 parents 9ce15e7 + 53aadbf commit 747901f
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -5,7 +5,7 @@
[![Docs](https://docs.rs/crc/badge.svg)](https://docs.rs/crc)
[![License](https://img.shields.io/crates/l/crc.svg?maxAge=2592000)](https://github.com/mrhooray/crc-rs#license)

Rust implementation of CRC(16, 32, 64). MSRV is 1.46.
Rust implementation of CRC(8, 16, 32, 64). MSRV is 1.46.

## Usage
Add `crc` to `Cargo.toml`
Expand Down
14 changes: 13 additions & 1 deletion benches/bench.rs
Expand Up @@ -2,10 +2,21 @@ use crc::*;
use criterion::{criterion_group, criterion_main};
use criterion::{Benchmark, Criterion, Throughput};

pub const BLUETOOTH: Crc<u8> = Crc::<u8>::new(&CRC_8_BLUETOOTH);
pub const X25: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_SDLC);
pub const CASTAGNOLI: Crc<u32> = Crc::<u32>::new(&CRC_32_ISCSI);
pub const ECMA: Crc<u64> = Crc::<u64>::new(&CRC_64_ECMA_182);

fn crc8(c: &mut Criterion) {
let mut digest = BLUETOOTH.digest();
let bytes = vec![0u8; 1_000_000];
c.bench(
"crc8",
Benchmark::new("crc8", move |b| b.iter(|| digest.update(&bytes)))
.throughput(Throughput::Bytes(1_000_000)),
);
}

fn crc16(c: &mut Criterion) {
let mut digest = X25.digest();
let bytes = vec![0u8; 1_000_000];
Expand Down Expand Up @@ -36,7 +47,8 @@ fn crc64(c: &mut Criterion) {
);
}

criterion_group!(crc8_benches, crc8);
criterion_group!(crc16_benches, crc16);
criterion_group!(crc32_benches, crc32);
criterion_group!(crc64_benches, crc64);
criterion_main!(crc16_benches, crc32_benches, crc64_benches);
criterion_main!(crc8_benches, crc16_benches, crc32_benches, crc64_benches);
64 changes: 64 additions & 0 deletions src/crc8.rs
@@ -0,0 +1,64 @@
use super::{Algorithm, Crc, Digest};
use crate::table::crc8_table;

impl Crc<u8> {
pub const fn new(algorithm: &'static Algorithm<u8>) -> Self {
let table = crc8_table(algorithm.poly, algorithm.refin);
Self { algorithm, table }
}

pub const fn checksum(&self, bytes: &[u8]) -> u8 {
let mut crc = self.init();
crc = self.update(crc, bytes);
self.finalize(crc)
}

const fn init(&self) -> u8 {
if self.algorithm.refin {
self.algorithm.init.reverse_bits()
} else {
self.algorithm.init
}
}

const fn table_entry(&self, index: u8) -> u8 {
self.table[index as usize]
}

const fn update(&self, mut crc: u8, bytes: &[u8]) -> u8 {
let mut i = 0;

while i < bytes.len() {
crc = self.table_entry(crc ^ bytes[i]);
i += 1;
}

crc
}

const fn finalize(&self, mut crc: u8) -> u8 {
if self.algorithm.refin ^ self.algorithm.refout {
crc = crc.reverse_bits();
}
crc ^ self.algorithm.xorout
}

pub const fn digest(&self) -> Digest<u8> {
Digest::new(self)
}
}

impl<'a> Digest<'a, u8> {
const fn new(crc: &'a Crc<u8>) -> Self {
let value = crc.init();
Digest { crc, value }
}

pub fn update(&mut self, bytes: &[u8]) {
self.value = self.crc.update(self.value, bytes);
}

pub const fn finalize(self) -> u8 {
self.crc.finalize(self.value)
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
@@ -1,5 +1,5 @@
//! # crc
//! Rust implementation of CRC(16, 32, 64)
//! Rust implementation of CRC(8, 16, 32, 64)
//!
//! ## Usage
//! ### Compute CRC16
Expand Down Expand Up @@ -35,6 +35,7 @@ pub use crc_catalog::*;
mod crc16;
mod crc32;
mod crc64;
mod crc8;
mod table;
mod util;

Expand Down
9 changes: 9 additions & 0 deletions src/table.rs
@@ -1,5 +1,14 @@
use crate::util::*;

pub(crate) const fn crc8_table(poly: u8, reflect: bool) -> [u8; 256] {
let mut table = [0u8; 256];
let mut i = 0;
while i < table.len() {
table[i] = crc8(poly, reflect, i as u8);
i += 1;
}
table
}
pub(crate) const fn crc16_table(poly: u16, reflect: bool) -> [u16; 256] {
let mut table = [0u16; 256];
let mut i = 0;
Expand Down
16 changes: 16 additions & 0 deletions src/util.rs
@@ -1,3 +1,19 @@
pub(crate) const fn crc8(poly: u8, reflect: bool, mut byte: u8) -> u8 {
if reflect {
byte = byte.reverse_bits()
};
let mut value = byte;
let mut i = 0;
while i < 8 {
value = (value << 1) ^ ((value >> 7) * poly);
i += 1;
}
if reflect {
value = value.reverse_bits()
}
value
}

pub(crate) const fn crc16(poly: u16, reflect: bool, mut byte: u8) -> u16 {
if reflect {
byte = byte.reverse_bits()
Expand Down
12 changes: 12 additions & 0 deletions tests/crc.rs
Expand Up @@ -2,6 +2,18 @@ use crc::*;

const INIT: &[u8] = b"123456789";

#[test]
fn crc_8() {
let algs = &[CRC_8_AUTOSAR, CRC_8_BLUETOOTH, CRC_8_SMBUS, CRC_8_DARC];
for alg in algs {
let crc = Crc::<u8>::new(alg);
assert_eq!(alg.check, crc.checksum(INIT));
let mut digest = crc.digest();
digest.update(INIT);
assert_eq!(alg.check, digest.finalize());
}
}

#[test]
fn crc_16() {
let algs = &[
Expand Down

0 comments on commit 747901f

Please sign in to comment.