Rust implementation of CRC(16, 32, 64) with support of various standards

Overview

crc

Build Status Crate Docs License

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

Usage

Add crc to Cargo.toml

[dependencies]
crc = "2.0"

Compute CRC

use crc::{Crc, Algorithm, CRC_16_IBM_SDLC, CRC_32_ISCSI};

pub const X25: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_SDLC);
pub const CASTAGNOLI: Crc<u32> = Crc::<u32>::new(&CRC_32_ISCSI);

assert_eq!(X25.checksum(b"123456789"), 0x906e);
assert_eq!(CASTAGNOLI.checksum(b"123456789"), 0xe3069283);

// use custom algorithm
const CUSTOM_ALG: Algorithm<u16> = Algorithm {
    poly: 0x8005,
    init: 0xffff,
    refin: false,
    refout: false,
    xorout: 0x0000,
    check: 0xaee7,
    residue: 0x0000
};
let crc = Crc::<u16>::new(&CUSTOM_ALG);
let mut digest = crc.digest();
digest.update(b"123456789");
assert_eq!(digest.finalize(), 0xaee7);

Benchmark

cargo bench with 2.6 GHz Intel Core i7. Comparison

crc16          time:   [2.0082 ms 2.0206 ms 2.0367 ms]
               thrpt:  [468.25 MiB/s 471.96 MiB/s 474.89 MiB/s]

crc32          time:   [1.7659 ms 1.7793 ms 1.7952 ms]
               thrpt:  [531.25 MiB/s 535.98 MiB/s 540.05 MiB/s]

crc64          time:   [2.0655 ms 2.0803 ms 2.0973 ms]
               thrpt:  [454.71 MiB/s 458.43 MiB/s 461.72 MiB/s]

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • Custom polynomials not working because crc-rs does not implement the complete CRC32 algorithm.

    Custom polynomials not working because crc-rs does not implement the complete CRC32 algorithm.

    Is there a reason you chose to implement the CRC32 algorithm in a reversed order?

    Everything from defining the polynomial to generating the lookup table to updating the CRC is reversed.

    In build.rs IEEE is defined as 0xedb88320 which is the reflected form of the correct polynomial 0x04C11DB7. Then make_table_crc32() works in a Little Endian way.

    I am currently using a custom polynomial and custom XOR value, and I cannot use your code in the current state. I have modified it to use the correct CRC32 algorithm. Are you interested in me making a pull request?

    opened by CLomanno 12
  • add no_std feature

    add no_std feature

    this adds support for no_std applications/libraries (like microcontrollers) by using conditional features

    • rust-lang/cargo#633

    On nightly with no_std:

    #  rustup run nightly cargo test --features no_std                                                                                                                                           <<<
        Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
         Running target/debug/deps/crc-c3e90d0dfab413be
    
    running 0 tests
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
    
         Running target/debug/deps/crc-9d7b680262789a74
    
    running 10 tests
    test crc32::checksum_castagnoli ... ok
    test crc32::checksum_ieee ... ok
    test crc32::digest_castagnoli ... ok
    test crc32::checksum_koopman ... ok
    test crc32::digest_ieee ... ok
    test crc64::checksum_ecma ... ok
    test crc32::digest_koopman ... ok
    test crc64::digest_iso ... ok
    test crc64::checksum_iso ... ok
    test crc64::digest_ecma ... ok
    
    test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured
    
         Running target/debug/deps/hash-bb44b103cb920ad0
    
    running 2 tests
    test hasher::checksum_hashcrc32 ... ok
    test hasher::checksum_hashcrc64 ... ok
    
    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
    
       Doc-tests crc
    
    running 2 tests
    test src/lib.rs -  (line 6) ... ok
    test src/lib.rs -  (line 27) ... ok
    
    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
    

    on stable with std:

    # rustup run stable cargo test                                                                                                                                                                 
       Compiling crc v1.4.0 (file:///home/garrett/projects/ruststuff/crc-rs)                                                                                                                                          
        Finished dev [unoptimized + debuginfo] target(s) in 1.64 secs                                                                                                                                                 
         Running target/debug/deps/crc-57a43f894e443797                                                                                                                                                               
                                                                                                                                                                                                                      
    running 0 tests
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
    
         Running target/debug/deps/crc-79b2fcd023832a0c                                                                                                                                                               
                                                                                                                                                                                                                      
    running 10 tests
    test crc32::checksum_castagnoli ... ok                                                                                                                                                                            
    test crc32::checksum_ieee ... ok                                                                                                                                                                                  
    test crc32::checksum_koopman ... ok                                                                                                                                                                               
    test crc32::digest_castagnoli ... ok                                                                                                                                                                              
    test crc32::digest_ieee ... ok                                                                                                                                                                                    
    test crc64::checksum_iso ... ok                                                                                                                                                                                   
    test crc64::checksum_ecma ... ok                                                                                                                                                                                  
    test crc64::digest_ecma ... ok                                                                                                                                                                                    
    test crc32::digest_koopman ... ok                                                                                                                                                                                 
    test crc64::digest_iso ... ok                                                                                                                                                                                     
                                                                                                                                                                                                                      
    test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured
    
         Running target/debug/deps/hash-da1e5eadb26ad3bb                                                                                                                                                              
                                                                                                                                                                                                                      
    running 2 tests
    test hasher::checksum_hashcrc32 ... ok
    test hasher::checksum_hashcrc64 ... ok
    
    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
    
       Doc-tests crc                                                                                                                                                                                                  
                                                                                                                                                                                                                      
    running 2 tests
    test src/lib.rs -  (line 27) ... ok                                                                                                                                                                               
    test src/lib.rs -  (line 6) ... ok                                                                                                                                                                                
                                                                                                                                                                                                                      
    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
    #
    
    
    opened by vitiral 11
  • which is CRC-16-CCITT?

    which is CRC-16-CCITT?

    How to calculate the well known CRC-16-CCITT with poly = 0x1021? according to https://www.lammertbies.nl/comm/info/crc-calculation and http://srecord.sourceforge.net/crc16-ccitt.html, we shall get 0xE5CC or 0x29B1 for bytes b"123456789", but I could not manage to get it. The combination I've tried the combination of poly in [0x8408, 0x1021] and init in [0, !0x1D0F], but with no luck.

      fn digest_crc(init: u16, poly: u16, input: &[u8]) -> u16 {
        use crc::crc16::Hasher16;
        let mut digest = crc::crc16::Digest::new_with_initial(poly, init);
        digest.write(input);
        !digest.sum16()
      }
      let input = b"123456789";
      digest_crc(0, 0x1021, input);
      digest_crc(0, 0x8408, input);
      digest_crc(!0x1D0F, 0x1021, input);
      digest_crc(!0x1D0F, 0x8408, input);
    

    I even tried poly of [0x811, 0x8810] according to this https://en.wikipedia.org/wiki/Cyclic_redundancy_check.

    opened by clouds56 10
  • Proposal for v2 API

    Proposal for v2 API

    Addresses a couple of different issues (https://github.com/mrhooray/crc-rs/pull/37, https://github.com/mrhooray/crc-rs/pull/46, https://github.com/mrhooray/crc-rs/issues/45, https://github.com/mrhooray/crc-rs/issues/40):

    • code duplication under the crc16, crc32, and crc64 modules
    • dependency on build scripts/macros (multiple Digests can share a crc table)
    // Crc
    
    pub trait Width: From<u8> + Into<u64> + Copy + 'static {}
    impl Width for u16 {}
    impl Width for u32 {}
    impl Width for u64 {}
    
    pub struct Algorithm<W: Width> {
        pub poly: W,
        pub init: W,
        pub xorout: W,
        pub check: W,
        pub residue: W,
        pub refin: bool,
        pub refout: bool,
    }
    
    pub const CRC_16_IBM_3740: Algorithm<u16> = Algorithm {
        poly: 0x1021, init: 0xffff,
        xorout: 0x0000, check: 0x29b1, residue: 0x0000,
        refin: false, refout: false,
    };
    pub const CRC_16_AUTOSAR: Algorithm<u16> = CRC_16_IBM_3740;
    
    pub struct Crc<W: Width> {
        algorithm: &'static Algorithm<W>,
        table: [W; 256],
    }
    
    impl<W: Width> Crc<W> {
        fn new(algorithm: &'static Algorithm<W>) -> Self {
            let table = make_table(algorithm.poly, algorithm.init);
            Crc { algorithm, table }
        }
    }
    
    // Digest
    
    pub struct Digest<'a, W: Width> {
        crc: &'a Crc<W>,
        value: W,
    }
    
    impl<'a, W: Width> Digest<'a, W> {
        fn new(crc: &'a Crc<W>) -> Self {
            let value = crc.algorithm.init;
            Digest { crc, value }
        }
    }
    
    impl<'a, W: Width> core::hash::Hasher for Digest<'a, W> {
        fn write(&mut self, bytes: &[u8]) {}
        fn finish(&self) -> u64 {
            unimplemented!()
        }
    }
    
    fn make_table<W: Width>(poly: W, init: W) -> [W; 256] {
        unimplemented!()
    }
    

    This represents a significant change in the API and internal structure of this library, but I believer the advantages are clear. Fully implementing these changes will take quite a bit of work. So, I wanted to get feedback before drafting a PR.

    opened by akhilles 10
  • Latest master commits not on crates.io

    Latest master commits not on crates.io

    Hello and thank you for the hard work you have put into this crate!

    I noticed that the latest commits to the master branch are 8 months old and have not yet been released on crates.io. The new_custom() method has been added to the various digests since the last release, and I think it would be useful to have this method available via downloads from crates.io.

    Would it be possible to create a new release? I would be more than happy to help out in anyway possible if there are outstanding issues that need to be resolved first.

    On a related note, would you be okay with me opening a pull request to address clippy lint warnings? The changes necessary to resolve the warnings are very minimal and shouldn't require much effort to review.

    opened by zachmse 9
  • Rust edition 2018, `no_std` default, README and CI changes

    Rust edition 2018, `no_std` default, README and CI changes

    • extern crate ...; is deprecated.
    • Cargo features should be used for "additive" functionality. So, it makes sense to remove the std feature.
    • Modifying features requires version bump since it could be a breaking change.
    opened by akhilles 9
  • Add Crc::digest_with_initial

    Add Crc::digest_with_initial

    It may sometimes be useful to compute CRC values with an initial value different from the one specified by the used algorithm. In this case, users currently have to create a new Algorithm for each initial value. This is particularly problematic if the initial values are not statically known, since Crc::new takes a static reference to an algorithm (see also #68). With the small change proposed in this PR, an initial value may optionally be supplied when creating a Digest.

    opened by voidc 6
  • Latest commit (479783b165f39db94e97cff3432855f5a3cc07f2) broke IEEE checksum, at least.

    Latest commit (479783b165f39db94e97cff3432855f5a3cc07f2) broke IEEE checksum, at least.

    I unfortunately lack time for a full repro right now, but maybe this will help. This code:

           let crc = u32::from_le_bytes(data[0..CRC_SIZE].try_into().map_err(|_| Error::DataSize)?);
           let computed_crc = crc32::checksum_ieee(&data[DATA_START..]);
    
           if crc != computed_crc {
               return Err(Error::Crc);
           }
    

    works right before that commit, but hits the error case after it.

    opened by mullr 6
  • mpeg2 crc32

    mpeg2 crc32

    I'd like to replace the following code implementing the 'mpeg2' crc32 with usage the crc-rs crate,

    https://github.com/dholroyd/mpeg2ts-reader/blob/master/src/mpegts_crc.rs

    Just plugging in the polynomial (0x04C11DB7 I think) didn't seem to work. Are there some extra pre/post processing steps required? I believe I tried inverting the result, but that didn't seem to be correct either.

    Thanks!

    opened by dholroyd 6
  • Standard CRC32 table based algorithm implemented.

    Standard CRC32 table based algorithm implemented.

    I had to redefine the polys and expected CRCs for everything in CRC32. However I modified the functions in crc32 so they are all backwards compatible.

    The new function new_with_initial_and_final() allows you to generate a reflected table with a custom initial and final XOR value.

    @mrhooray Sorry, this is my first pull request and I didn't add a reviewer, assignee, or label.

    opened by CLomanno 6
  • CRC Computation Question

    CRC Computation Question

    I'm having trouble getting the crc32 computation to match what I'm seeing in Ceph.
    I have an example here where at the top is a C++ unit test and on the bottom is the Rust code I'm using to try and reproduce it. It's close but doesn't match.

    https://play.rust-lang.org/?gist=6bca7e3630d48f9225e5&version=stable

    opened by cholcombe973 4
  • How to upgrade from v1 to v3 API?

    How to upgrade from v1 to v3 API?

    This is more of a question rather than an issue.

    I have one line code written with v1 API:

    let checksum = crc32::update(my_u32, &crc32::IEEE_TABLE, mybytes).to_be_bytes();
    

    I tried to translate to V3 API:

    let CRC_32_IEEE: Crc<u32> = Crc::<u32>::new(&CRC_32_ISO_HDLC);
    let mut digest = CRC_32_IEEE.digest_with_initial(my_u32);
    digest.update(mybytes);
    let checksum = digest.finalize();
    

    But the result has changed.

    Any ideas? Thanks

    opened by soulmachine 0
  • recommended method for keeping a `Digest` in a struct w/ 3.0 API

    recommended method for keeping a `Digest` in a struct w/ 3.0 API

    Hello,

    I'm trying to make a wrapper for a std::io::Write object that keeps a running CRC. This looks something like this:

    struct Wrapper<W> {
       w: W,
       crc: Crc<u32>,
    }
    
    impl <W: std::io::Write> std::io::Write for Wrapper {
        fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
            self.crc.digest().update(buf);
            self.w.write(buf)
        }
    }
    

    However this is wrong, because the running state of the digest gets discarded on every write call (i think). I feel like what I want is crc.update(), but it's not pub. I could also figure out a way to store both the crc and the digest in the struct, but that would involve internal references, which are a pain to work with.

    Is there some recommended way to do this? Is this a good case for making Crc::update pub?

    opened by james-rms 6
  • fix benchmarks

    fix benchmarks

    Hi,

    I did a couple of straight-forward changes such that cargo bench works again. I also fixed the deprecation warnings in the benchmarks ~and changed the rust edition to 2021~.

    Let me know if you want anything changed.

    opened by fkohlgrueber 4
  • Add a const fn version of digest update

    Add a const fn version of digest update

    So for context, I'm working on a library for a special type of hash which involves a CRC32, but the implementation takes every character and makes it lowercase (ascii_lowercase) before it's hashed. Since this is a const fn, I'm not able to create a new allocations for the lowercased version. I've tried const generics, but that requires always knowing the input length at compile time, which is too restrictive. I've found a way to do this, by adding a const fn version of the update function in Digest, which I've implemented in this PR. Here's an example using it:

    pub struct Hash40(pub u64);
    
    pub const fn new(string: &str) -> Hash40 {
        let bytes = string.as_bytes();
        let algo = Crc::<u32>::new(&CRC_32_CKSUM);
        let mut digest = algo.digest();
        let mut index = 0;
        while index < string.len() {
            digest = digest.updated(&[bytes[index]]);
            index += 1;
        }
        let crc = digest.finalize() as u64;
        let length_byte = (string.len() as u8 as u64) << 32;
        Hash40(crc | length_byte)
    }
    

    This is kind of an undesirable way to calculate the hash anyway, so if we can find some other way to write this, that would be cool too

    opened by benhall-7 2
  • `Crc::new` doesn't need to require a `'static` `Algorithm` reference

    `Crc::new` doesn't need to require a `'static` `Algorithm` reference

    This restricts how a program could construct a custom algorithm locally ands use it on the fly.

    I noticed that the current internal of Crc holds the reference. Relaxing the lifetime means Crc would need a lifetime parameter as well, which is a breaking change unfortunately. An alternative way is to let Crc clone the data Algorithm has.

    opened by wwylele 5
Releases(3.0.0)
  • 3.0.0(Apr 23, 2022)

    Bartel Sielski (2):
          Add support for CRC algorithms which have a non-power of 2 width
          Add support for up to 128 bit CRCs
    
    Dominik Stolz (1):
          Add Crc::digest_with_initial
    
    Cliff L. Biffle (1):
          impl Clone for Digest
    
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Oct 28, 2021)

Owner
Rui Hu
Rui Hu
Character encoding support for Rust

Encoding 0.3.0-dev Character encoding support for Rust. (also known as rust-encoding) It is based on WHATWG Encoding Standard, and also provides an ad

Kang Seonghoon 264 Dec 14, 2022
A CSV parser for Rust, with Serde support.

csv A fast and flexible CSV reader and writer for Rust, with support for Serde. Dual-licensed under MIT or the UNLICENSE. Documentation https://docs.r

Andrew Gallant 1.3k Jan 5, 2023
TLV-C encoding support.

TLV-C: Tag - Length - Value - Checksum TLV-C is a variant on the traditional [TLV] format that adds a whole mess of checksums and whatnot. Why, you as

Oxide Computer Company 3 Nov 25, 2022
MessagePack implementation for Rust / msgpack.org[Rust]

RMP - Rust MessagePack RMP is a pure Rust MessagePack implementation. This repository consists of three separate crates: the RMP core and two implemen

Evgeny Safronov 840 Dec 30, 2022
Implementation of Bencode encoding written in rust

Rust Bencode Implementation of Bencode encoding written in rust. Project Status Not in active developement due to lack of time and other priorities. I

Arjan Topolovec 32 Aug 6, 2022
A Gecko-oriented implementation of the Encoding Standard in Rust

encoding_rs encoding_rs an implementation of the (non-JavaScript parts of) the Encoding Standard written in Rust and used in Gecko (starting with Fire

Henri Sivonen 284 Dec 13, 2022
PROST! a Protocol Buffers implementation for the Rust Language

PROST! prost is a Protocol Buffers implementation for the Rust Language. prost generates simple, idiomatic Rust code from proto2 and proto3 files. Com

Dan Burkert 17 Jan 8, 2023
Rust implementation of Google protocol buffers

rust-protobuf Protobuf implementation in Rust. Written in pure rust Generate rust code Has runtime library for generated code (Coded{Input|Output}Stre

Stepan Koltsov 2.3k Dec 31, 2022
A fast, performant implementation of skip list in Rust.

Subway A fast, performant implementation of skip list in Rust. A skip list is probabilistic data structure that provides O(log N) search and insertion

Sushrut 16 Apr 5, 2022
Pure Rust port of CRFsuite: a fast implementation of Conditional Random Fields (CRFs)

crfs-rs Pure Rust port of CRFsuite: a fast implementation of Conditional Random Fields (CRFs) Currently only support prediction, model training is not

messense 24 Nov 23, 2022
A binary encoder / decoder implementation in Rust.

Bincode A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme. The size of the encoded object will be the same or smaller tha

Bincode 1.9k Dec 29, 2022
rust-jsonnet - The Google Jsonnet( operation data template language) for rust

rust-jsonnet ==== Crate rust-jsonnet - The Google Jsonnet( operation data template language) for rust Google jsonnet documet: (http://google.github.io

Qihoo 360 24 Dec 1, 2022
A Rust ASN.1 (DER) serializer.

rust-asn1 This is a Rust library for parsing and generating ASN.1 data (DER only). Installation Add asn1 to the [dependencies] section of your Cargo.t

Alex Gaynor 85 Dec 16, 2022
Rust library for reading/writing numbers in big-endian and little-endian.

byteorder This crate provides convenience methods for encoding and decoding numbers in either big-endian or little-endian order. Dual-licensed under M

Andrew Gallant 811 Jan 1, 2023
Cap'n Proto for Rust

Cap'n Proto for Rust documentation blog Introduction Cap'n Proto is a type system for distributed systems. With Cap'n Proto, you describe your data an

Cap'n Proto 1.5k Dec 26, 2022
A HTTP Archive format (HAR) serialization & deserialization library, written in Rust.

har-rs HTTP Archive format (HAR) serialization & deserialization library, written in Rust. Install Add the following to your Cargo.toml file: [depende

Sebastian Mandrean 25 Dec 24, 2022
A HTML entity encoding library for Rust

A HTML entity encoding library for Rust Example usage All example assume a extern crate htmlescape; and use htmlescape::{relevant functions here}; is

Viktor Dahl 41 Nov 1, 2022
pem-rs pem PEM jcreekmore/pem-rs [pem] — A Rust based way to parse and encode PEM-encoded data

pem A Rust library for parsing and encoding PEM-encoded data. Documentation Module documentation with examples Usage Add this to your Cargo.toml: [dep

Jonathan Creekmore 30 Dec 27, 2022
tnetstring serialization library for rust.

TNetStrings: Tagged Netstrings This module implements bindings for the tnetstring serialization format. API let t = tnetstring::str("hello world"); le

Erick Tryzelaar 16 Jul 14, 2019