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

Standard CRC32 table based algorithm implemented. #32

Merged
merged 17 commits into from
May 31, 2018

Conversation

CLomanno
Copy link
Contributor

@CLomanno CLomanno commented Apr 17, 2018

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.

…in table generation and crc calculation.

Maintained reverse compatability with v1.7.0 and added docs
@CLomanno
Copy link
Contributor Author

I found the default values for various 32bit crc standards here: https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations_of_cyclic_redundancy_checks

Verified the correct crc values here: http://crccalc.com/

@CLomanno
Copy link
Contributor Author

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

@CLomanno
Copy link
Contributor Author

@mrhooray I completed updating all 3 CRC types. Now crc16, crc32, and crc64 are backwards compatible and can work normal or reflected.

Copy link
Owner

@mrhooray mrhooray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @CLomanno for updating the pr, left a few minor comments and gonna play around with it locally.

also added you as collaborator for this module since you care a lot about correctness, backward compatibility, users, etc

Cargo.toml Outdated
@@ -12,6 +12,13 @@ license = "MIT OR Apache-2.0"
[build-dependencies]
build_const = "0.2"

#[dev-dependencies]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we remove unrelated changes or you want to move benchmarks to use criterion instead in this pr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Criteron is nice, but we can use whatever you want. I left both in for you to choose

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, let's remove the commented code and revisit benchmark framework in separate pr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, Criterion adds a lot of bloat. I'll save the code for later in case it needs added back in

benches/bench.rs Outdated
}

/*
#[macro_use]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

src/crc16.rs Outdated
///
/// *table:* Holds the table values based on the supplied polynomial for the fast CRC calculations
///
/// *initial:* The initial inut value. AKA reflect_in
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: input instead of inut, and a few other occurrences in this pr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the comments were copy/pasted between crc16/32/64

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to keep it, or it's actually a typo?

src/util.rs Outdated
}

/// Reflects the lease significant byte of a u32.
pub fn reflect_long_32(input: u32) -> u32 {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have following 3 functions named consistently like reflect_byte_16/32/64?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed to reflect_value_16 etc.

src/util.rs Outdated
}
table
}

/// Reflects a value of a 16 bit number
pub fn reflect_short(mut value: u16) -> u16 {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reflect_16/32/64 or something similar?
just to make things consistent with next set of 3 functions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed to reflect_byte_16 etc.

Copy link

@nickbabcock nickbabcock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the sudden influx of comments. I'm interested in seeing if I can replace code I've written with this crate, so I'd thought I'd voice my opinions 😄

src/crc16.rs Outdated
for &i in bytes.iter() {
value = table[((value as u8) ^ i) as usize] ^ (value >> 8)
if true == rfl {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test for reflection should be hoisted outside the loop to avoid the needless conditional check for each byte. Also I feel like

if rfl {
}

is more idiomatic than

if true == rfl {
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to just if rfl {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to take it out of the update() function. I couldn't cleanly get it out of make_table_crcXX()

src/crc16.rs Outdated
}

impl Digest {
/// *Only works for reflected CRCs*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have you taken a look at how these docs render? If you are intending for there to be a space between this and the next sentence I believe you'll a new line, else it might just render as a single paragraph

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Fixed

src/crc32.rs Outdated
///
/// # Definitions
///
/// *table:* Holds the table values based on the supplied polynomial for the fast CRC calculations

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may have better luck with formatting with lists

- table: Holds the table values based on the supplied polynomial for the fast CRC calculations
- initial: 
- reflect: 

Copy link
Contributor Author

@CLomanno CLomanno May 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

src/util.rs Outdated
pub fn make_table_crc16(poly: u16) -> [u16; 256] {
/// Builds a CRC16 table using the standard or reflected CRC method
/// If reflect==true, flip the individual byte bitwise, then flip the 32bit table value bitwise
pub fn make_table_crc16(poly: u16, rfl: bool) -> [u16; 256] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If in the rustdoc you mention the reflect parameter, shouldn't the parameter be reflect: bool instead of rfl: bool.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@nickbabcock
Copy link

As a side note, I benchmarked this impl against:

pub fn calc_crc(data: &[u8]) -> u32 {
    !data.iter().fold(!0xefcb_f201, |acc, &x| {
        (acc << 8) ^ (TABLE[((u32::from(x)) ^ (acc >> 24)) as usize])
    })
}

Both produce the same output (:+1:), but this PR is 10-15% slower.

For reference, I wrote:

lazy_static! {
    static ref TABLE: [u32; 256] = make_table(0x04c11db7, false);
}

pub fn calc_crc(data: &[u8]) -> u32 {
    !update(!0xefcb_f201, &TABLE, data, false)
}

@CLomanno
Copy link
Contributor Author

CLomanno commented May 30, 2018

@nickbabcock I like your speed improvement. I put it in! It also got rid of the if rfl { check per iteration

@mrhooray mrhooray merged commit 654d7da into mrhooray:master May 31, 2018
@mrhooray
Copy link
Owner

thanks @CLomanno @nickbabcock
will update readme etc and release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants