diff --git a/.gitignore b/.gitignore index 593c5e8..55261a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,12 @@ build tags + +# Rust and Cargo +Cargo.lock +target/ + +#IDE +.idea + +# CMake +cmake-build-debug diff --git a/aws_crt_checksums_ws/Cargo.toml b/aws_crt_checksums_ws/Cargo.toml new file mode 100644 index 0000000..d441ff3 --- /dev/null +++ b/aws_crt_checksums_ws/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "aws-crt-checksums", + "aws-crt-checksums-sys", +] + diff --git a/aws_crt_checksums_ws/aws-crt-checksums-sys/Cargo.toml b/aws_crt_checksums_ws/aws-crt-checksums-sys/Cargo.toml new file mode 100644 index 0000000..9a8df6a --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums-sys/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "aws-crt-checksums-sys" +version = "0.1.0" +authors = ["AWS Common Runtime Team (aws-sdk-common-runtime-team@amazon.com)"] +edition = "2018" +links = "aws-checksums" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[build-dependencies] +aws-crt-c-flags = { git = "https://github.com/awslabs/aws-c-common", branch="move_to_rust_phase1" } + +[dependencies] +aws-crt-common-sys = { git = "https://github.com/awslabs/aws-c-common", branch="move_to_rust_phase1" } diff --git a/aws_crt_checksums_ws/aws-crt-checksums-sys/build.rs b/aws_crt_checksums_ws/aws-crt-checksums-sys/build.rs new file mode 100644 index 0000000..d8631a9 --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums-sys/build.rs @@ -0,0 +1,73 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +use aws_crt_c_flags::{CRTModuleBuildInfo, HeaderType}; +use std::path::Path; + +fn main() { + let mut build_info = CRTModuleBuildInfo::new("aws-checksums"); + build_info.module_links_dependency("aws-c-common"); + + let include_path = Path::new("../../include/aws"); + build_info.include_dir(include_path, HeaderType::Public); + + build_info + .file(Path::new("../../source/crc.c")) + .file(Path::new("../../source/crc_sw.c")); + + // rustc seems to be wrong on this one. + #[allow(unused_mut)] + #[allow(unused_assignments)] + let mut impl_found = false; + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if build_info.follows_msvc_semantics() { + build_info.file(Path::new( + "../../source/intel/visualc/visualc_crc32c_sse42.c", + )); + } else { + build_info.file(Path::new("../../source/intel/asm/crc32c_sse42_asm.c")); + } + impl_found = true; + } + + #[cfg(target_arch = "aarch64")] + { + build_info.file(Path::new("../../source/arm/crc32c_arm.c")); + + if !build_info.follows_msvc_semantics() { + build_info.private_cflag("-march=armv8-a+crc"); + } + impl_found = true; + } + + #[cfg(all(target_arch = "arm"))] + { + if !build_info.follows_msvc_semantics() { + if build_info + .try_compile( + "#include + int main() { + int crc = __crc32d(0, 1); + return 0; + }", + ) + .is_ok() + { + build_info + .private_cflag("-march=armv8-a+crc") + .private_define("AWS_ARM32_CRC", "1"); + build_info.file(Path::new("../../source/arm/crc32c_arm.c")); + impl_found = true; + } + } + } + + if !impl_found { + build_info.file(Path::new("../../source/generic/crc32c_null.c")); + } + + build_info.build(); +} diff --git a/aws_crt_checksums_ws/aws-crt-checksums-sys/src/lib.rs b/aws_crt_checksums_ws/aws-crt-checksums-sys/src/lib.rs new file mode 100644 index 0000000..a6ab5e6 --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums-sys/src/lib.rs @@ -0,0 +1,13 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +/// This module is a rust translation of the relevant declarations from the aws-c-common +/// header files. They are used from higher-level wrapper modules. + +#[allow(dead_code)] +extern "C" { + pub fn aws_checksums_crc32(input: *const u8, length: i32, previous_crc: u32) -> u32; + pub fn aws_checksums_crc32c(input: *const u8, length: i32, previous_crc: u32) -> u32; +} diff --git a/aws_crt_checksums_ws/aws-crt-checksums/Cargo.toml b/aws_crt_checksums_ws/aws-crt-checksums/Cargo.toml new file mode 100644 index 0000000..443a895 --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "aws-crt-checksums" +version = "0.1.0" +authors = ["AWS Common Runtime Team (aws-sdk-common-runtime-team@amazon.com)"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aws-crt-checksums-sys = { path = "../aws-crt-checksums-sys" } +aws-crt-common = { git = "https://github.com/awslabs/aws-c-common", branch="move_to_rust_phase1" } diff --git a/aws_crt_checksums_ws/aws-crt-checksums/src/lib.rs b/aws_crt_checksums_ws/aws-crt-checksums/src/lib.rs new file mode 100644 index 0000000..dfd07b2 --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums/src/lib.rs @@ -0,0 +1,76 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +use aws_crt_checksums_sys::{aws_checksums_crc32, aws_checksums_crc32c}; + +#[derive(Clone)] +pub struct Crc32C { + running_checksum: u32, +} + +#[derive(Clone)] +pub struct Crc32 { + running_checksum: u32, +} + +/// Trait for computing running checksums. +pub trait Checksum { + type Output; + /// update the checksum with the checksum value of input + /// # Arguments + /// * `input` the input data to be appended to the running checksum. + fn update(&mut self, input: &Vec); + /// Return the current value of the running checksum. + fn checksum(&self) -> Self::Output; +} + +impl Checksum for Crc32C { + type Output = u32; + + fn update(&mut self, input: &Vec) { + unsafe { + self.running_checksum = + aws_checksums_crc32c(input.as_ptr(), input.len() as i32, self.running_checksum); + } + } + + fn checksum(&self) -> u32 { + self.running_checksum + } +} + +impl Checksum for Crc32 { + type Output = u32; + + fn update(&mut self, input: &Vec) { + unsafe { + self.running_checksum = + aws_checksums_crc32(input.as_ptr(), input.len() as i32, self.running_checksum); + } + } + + fn checksum(&self) -> u32 { + self.running_checksum + } +} + +impl Crc32C { + /// Creates a new instance of the castagnoli CRC32c (iSCSI) checksum algorithm. Where supported + /// by the hardware, this implementation is hw accelerated. + pub fn new() -> Crc32C { + Crc32C { + running_checksum: 0, + } + } +} + +impl Crc32 { + /// Creates a new instance of the CRC32 (Ethernet, gzip) algorithm. Where supported + /// by the hardware, this implementation is hw accelerated. + pub fn new() -> Crc32 { + Crc32 { + running_checksum: 0, + } + } +} diff --git a/aws_crt_checksums_ws/aws-crt-checksums/tests/lib.rs b/aws_crt_checksums_ws/aws-crt-checksums/tests/lib.rs new file mode 100644 index 0000000..b7c7b44 --- /dev/null +++ b/aws_crt_checksums_ws/aws-crt-checksums/tests/lib.rs @@ -0,0 +1,55 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#[cfg(test)] +mod tests { + use aws_crt_checksums::{Checksum, Crc32, Crc32C}; + + #[test] + fn test_crc32_zeroes() { + let test_input: Vec = vec![0; 32]; + let expected_crc = 0x190A55AD; + + let mut crc_checksum = Crc32::new(); + crc_checksum.update(&test_input); + assert_eq!(expected_crc, crc_checksum.checksum()); + } + + #[test] + fn test_known_crc32() { + let test_input: Vec = vec![ + '1' as u8, '2' as u8, '3' as u8, '4' as u8, '5' as u8, '6' as u8, '7' as u8, '8' as u8, + '9' as u8, + ]; + let expected_crc = 0xCBF43926; + + let mut crc_checksum = Crc32::new(); + crc_checksum.update(&test_input); + assert_eq!(expected_crc, crc_checksum.checksum()); + } + + #[test] + fn test_crc32c_zeroes() { + let test_input: Vec = vec![0; 32]; + let expected_crc = 0x8A9136AA; + + let mut crc_checksum = Crc32C::new(); + crc_checksum.update(&test_input); + assert_eq!(expected_crc, crc_checksum.checksum()); + } + + #[test] + fn test_known_crc32c() { + let test_input: Vec = vec![ + '1' as u8, '2' as u8, '3' as u8, '4' as u8, '5' as u8, '6' as u8, '7' as u8, '8' as u8, + '9' as u8, + ]; + let expected_crc = 0xE3069283; + + let mut crc_checksum = Crc32C::new(); + crc_checksum.update(&test_input); + assert_eq!(expected_crc, crc_checksum.checksum()); + } +}