diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fc580b6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,198 @@ +name: CI + +on: + push: + branches: + - main + - "*.*" + pull_request: + branches: + - "*" + schedule: + - cron: "0 0 * * MON" + +env: + CARGO_TERM_COLOR: always + +jobs: + lock: + name: Cargo.lock + runs-on: ubuntu-latest + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + profile: minimal + override: true + + - name: Generate the minimum version lockfile + run: | + cargo update -Z minimal-versions + cargo update -Z direct-minimal-versions + mv Cargo.lock Cargo.lock.min + + - name: Generate the current version lockfile + run: cargo update + + - name: Upload the Cargo lockfiles + uses: actions/upload-artifact@v4 + with: + name: Cargo.lock + path: | + Cargo.lock + Cargo.lock.min + + check: + name: Check + strategy: + matrix: + os: [ubuntu-latest] + rust: ["1.85", stable, nightly] + lock: ["Cargo.lock", "Cargo.lock.min"] + runs-on: ${{ matrix.os }} + needs: lock + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + with: + submodules: true + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + + - name: Install power tools + uses: taiki-e/install-action@cargo-hack + + - name: Download the Cargo lockfiles + uses: actions/download-artifact@v4 + with: + name: Cargo.lock + + - name: Rename ${{ matrix.lock }} to Cargo.lock + run: mv ${{ matrix.lock }} Cargo.lock + if: ${{ matrix.lock != 'Cargo.lock' }} + + - name: Check the powerset + run: | + cargo hack check --all \ + --feature-powerset --keep-going + + test: + name: Test Suite + strategy: + matrix: + os: [ubuntu-latest] + rust: [stable] + lock: ["Cargo.lock", "Cargo.lock.min"] + runs-on: ${{ matrix.os }} + needs: lock + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + with: + submodules: true + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + + - name: Install power tools + uses: taiki-e/install-action@cargo-hack + + - name: Download the Cargo lockfiles + uses: actions/download-artifact@v4 + with: + name: Cargo.lock + + - name: Rename ${{ matrix.lock }} to Cargo.lock + run: mv ${{ matrix.lock }} Cargo.lock + if: ${{ matrix.lock != 'Cargo.lock' }} + + - name: Run the test-suite powerset + run: | + cargo hack test --workspace \ + --no-fail-fast --feature-powerset --keep-going \ + --release + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + profile: minimal + components: rustfmt + override: true + + - name: Check the code formatting + run: cargo fmt --all -- --check + + clippy: + name: Clippy + strategy: + matrix: + os: [ubuntu-latest] + rust: ["1.85", stable] + lock: ["Cargo.lock", "Cargo.lock.min"] + runs-on: ${{ matrix.os }} + needs: lock + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + with: + submodules: true + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + components: clippy + override: true + + - name: Install power tools + uses: taiki-e/install-action@cargo-hack + + - name: Download the Cargo lockfiles + uses: actions/download-artifact@v4 + with: + name: Cargo.lock + + - name: Rename ${{ matrix.lock }} to Cargo.lock + run: mv ${{ matrix.lock }} Cargo.lock + if: ${{ matrix.lock != 'Cargo.lock' }} + + - name: Check the code style powerset + if: ${{ matrix.rust == 'stable' && matrix.lock == 'Cargo.lock' }} + run: | + cargo hack clippy --all \ + --feature-powerset --keep-going \ + -- -D warnings + + - name: Check the code style powerset + if: ${{ matrix.rust != 'stable' || matrix.lock != 'Cargo.lock' }} + run: | + cargo hack clippy --all \ + --feature-powerset --keep-going \ + -- -D warnings -A unknown-lints -A clippy::multiple-crate-versions diff --git a/.github/workflows/rustdoc.yml b/.github/workflows/rustdoc.yml new file mode 100644 index 0000000..a2e2250 --- /dev/null +++ b/.github/workflows/rustdoc.yml @@ -0,0 +1,47 @@ +name: rustdoc to gh-pages + +on: + push: + branches: + - main + +env: + CARGO_TERM_COLOR: always + +jobs: + release: + name: GitHub Pages + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + with: + submodules: true + + - name: Install the Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + + - name: Build the Documentation + run: | + RUSTDOCFLAGS="\ + --enable-index-page \ + --generate-link-to-definition \ + -Zunstable-options\ + " cargo doc \ + --all-features \ + --no-deps \ + --workspace + + - name: Deploy the Documentation + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./target/doc + keep_files: false diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3999dd0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "libpressio-sys/libpressio"] + path = libpressio-sys/libpressio + url = https://github.com/robertu94/libpressio.git +[submodule "libpressio-sys/std_compat"] + path = libpressio-sys/std_compat + url = https://github.com/robertu94/std_compat diff --git a/Cargo.toml b/Cargo.toml index dac5db1..792bc25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,41 @@ +[workspace] +resolver = "2" +members = ["libpressio-sys"] + +[workspace.package] +edition = "2024" +authors = ["Robert Underwood "] +repository = "https://github.com/robertu94/libpressio-rs" +rust-version = "1.85" + +[workspace.dependencies] +# workspace-internal crates +libpressio = { version = "0.1", path = ".", default-features = false } +libpressio-sys = { version = "0.1", path = "libpressio-sys", default-features = false } + +# crates.io third-party dependencies +bindgen = { version = "0.71", default-features = false } +cc = { version = "1.2", default-features = false } +cmake = { version = "0.1.26", default-features = false } +libc = { version = "0.2", default-features = false } +ndarray = { version = "0.16.1", default-features = false } + [package] -name = "libpressio-rs" +name = "libpressio" version = "0.1.0" -authors = ["Robert Underwood "] -edition = "2018" +edition = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +description = "High-level Rust bindings to the libpressio compression framework" +categories = ["api-bindings", "compression", "encoding"] +keywords = ["libpressio", "compression", "encoding"] -[dependencies] -ndarray = "0.14.0" -libc = "0.2.86" +[features] +openmp = ["libpressio-sys/openmp"] -[build-dependencies] -bindgen = "0.53.1" -pkg-config = "0.3.19" +[dependencies] +ndarray = { workspace = true } +libc = { workspace = true } +libpressio-sys = { workspace = true } diff --git a/build.rs b/build.rs deleted file mode 100644 index 90d5f23..0000000 --- a/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -extern crate bindgen; -extern crate pkg_config; - -use std::env; -use std::path::PathBuf; - -pub fn main() { - println!("cargo:rustc-link-lib=libpressio"); - println!("cargo:rerun-if-changed=./build/wrapper.h"); - println!("cargo:rerun-if-changed=./build.rs"); - - let libpressio = pkg_config::probe_library("libpressio").unwrap(); - let include_flag = format!("-I{}", libpressio.include_paths[0].to_str().unwrap()); - //println!("{}", include_flag); - - let bindings = bindgen::Builder::default() - .header("./build/wrapper.h") - .clang_arg(include_flag) - .whitelist_function("pressio_.*") - .whitelist_var("pressio_.*") - .whitelist_type("pressio_.*") - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) - .generate() - .expect("unable to generate bindings"); - let output = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(output.join("bindings.rs")) - .expect("couldn't write bindings"); -} diff --git a/libpressio-sys/Cargo.toml b/libpressio-sys/Cargo.toml new file mode 100644 index 0000000..8dee8a0 --- /dev/null +++ b/libpressio-sys/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "libpressio-sys" +version = "0.1.0" +edition = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } + +description = "Low-level Rust bindings to the libpressio compression framework" +readme = "README.md" +categories = ["api-bindings", "compression", "encoding"] +keywords = ["libpressio", "bindgen", "compression", "encoding"] + +[features] +# For now, enabling the `openmp` feature assumes that OpenMP is pre-installed +openmp = [] + +[build-dependencies] +anyhow = "1.0.98" +bindgen = { workspace = true, features = ["runtime"] } +cc = { workspace = true } +cmake = { workspace = true } +regex = "1.11.1" diff --git a/libpressio-sys/build.rs b/libpressio-sys/build.rs new file mode 100644 index 0000000..e257818 --- /dev/null +++ b/libpressio-sys/build.rs @@ -0,0 +1,126 @@ +use std::{ + env, + path::PathBuf, +}; + +#[derive(Debug)] +struct CargoCallBacksIngoreGeneratedFiles { + cargo_callbacks: bindgen::CargoCallbacks, + files: std::vec::Vec +} +impl CargoCallBacksIngoreGeneratedFiles { + fn new<'a, T>(files: T) -> Result + where T : IntoIterator + { + Ok(CargoCallBacksIngoreGeneratedFiles { + cargo_callbacks: bindgen::CargoCallbacks::new(), + files: Vec::from_iter(files.into_iter().map(|v| regex::Regex::new(v).unwrap())) + }) + } +} +impl bindgen::callbacks::ParseCallbacks for CargoCallBacksIngoreGeneratedFiles { + fn header_file(&self, filename: &str) { + if !self.files.iter().any(|f| f.is_match(filename)) { + self.cargo_callbacks.header_file(filename) + } + } + fn include_file(&self, filename: &str) { + if !self.files.iter().any(|f| f.is_match(filename)) { + self.cargo_callbacks.include_file(filename) + } + } + fn read_env_var(&self, filename: &str) { + self.cargo_callbacks.read_env_var(filename) + } +} + +fn main() -> Result<(), Box> { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=wrapper.h"); + println!("cargo::rerun-if-changed=libpressio"); + println!("cargo::rerun-if-changed=std_compat"); + + // --------------------------------------------------------- + // Configure std_compat, the compiler portability layer + // --------------------------------------------------------- + let mut stdcompat_config = cmake::Config::new("std_compat"); + //prefer static libraries for RUST + stdcompat_config.define("BUILD_SHARED_LIBS", "OFF"); + //disable testing to avoid google-test dependency + stdcompat_config.define("BUILD_TESTING", "OFF"); + // require a C++17 compiler (e.g. gcc 12 or later) for now + // this includes Ubuntu 24.04 and later, Fedora, Nyx, et al + // https://robertu94.github.io/guides/dependencies + stdcompat_config.define("STDCOMPAT_CXX_VERSION", "17"); + stdcompat_config.define("STDCOMPAT_CXX_UNSTABLE", "ON"); + stdcompat_config.define("STD_COMPAT_BOOST_REQUIRED", "OFF"); + let stdcompat_out = stdcompat_config.build(); + println!( + "cargo::rustc-link-search=native={}", + stdcompat_out.display() + ); + + // --------------------------------------------------------- + // Configure libpressio + // --------------------------------------------------------- + let mut config = cmake::Config::new("libpressio"); + config.define("BUILD_SHARED_LIBS", "OFF"); + config.define("BUILD_TESTING", "OFF"); + config.define( + "LIBPRESSIO_HAS_OPENMP", + if cfg!(feature = "openmp") { + "ON" + } else { + "OFF" + }, + ); + config.define("CMAKE_PREFIX_PATH", stdcompat_out); + let libpressio_out = config.build(); + + println!("cargo:rustc-link-lib=static=libpressio"); + #[cfg(target_os = "linux")] + println!("cargo:rustc-link-lib=dylib=stdc++"); + println!( + "cargo::rustc-link-search=native={}", + libpressio_out.display() + ); + println!( + "cargo::rustc-link-search=native={}", + libpressio_out.join("lib").display() + ); + println!( + "cargo::rustc-link-search=native={}", + libpressio_out.join("lib64").display() + ); + println!("cargo::rustc-link-lib=static=libpressio"); + + let cargo_callbacks = CargoCallBacksIngoreGeneratedFiles::new(["pressio_version.h"])?; + let bindings = bindgen::Builder::default() + .clang_arg("-x") + .clang_arg("c++") + .clang_arg("-std=c++11") + .clang_arg(format!( + "-I{}", + libpressio_out.join("include").join("libpressio").display() + )) + .header("wrapper.h") + .parse_callbacks(Box::new(cargo_callbacks)) + .allowlist_function("pressio_.*") + .allowlist_var("pressio_.*") + .allowlist_type("pressio_.*") + // MSRV 1.85 + .rust_target(match bindgen::RustTarget::stable(85, 0) { + Ok(target) => target, + #[expect(clippy::panic)] + Err(err) => panic!("{err}"), + }) + .generate() + .expect("Unable to generate bindings"); + + let out_path = + PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR should be set in a build script")); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); + Ok(()) +} diff --git a/libpressio-sys/libpressio b/libpressio-sys/libpressio new file mode 160000 index 0000000..11a1edf --- /dev/null +++ b/libpressio-sys/libpressio @@ -0,0 +1 @@ +Subproject commit 11a1edf696ef908405ed4bf84c9d9a99fada1139 diff --git a/libpressio-sys/src/lib.rs b/libpressio-sys/src/lib.rs new file mode 100644 index 0000000..2474ec1 --- /dev/null +++ b/libpressio-sys/src/lib.rs @@ -0,0 +1,4 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/libpressio-sys/std_compat b/libpressio-sys/std_compat new file mode 160000 index 0000000..76b61ae --- /dev/null +++ b/libpressio-sys/std_compat @@ -0,0 +1 @@ +Subproject commit 76b61aed61bff2a468949f9c620c3a8900fc8d91 diff --git a/libpressio-sys/wrapper.h b/libpressio-sys/wrapper.h new file mode 100644 index 0000000..102c168 --- /dev/null +++ b/libpressio-sys/wrapper.h @@ -0,0 +1 @@ +#include "libpressio/include/libpressio.h" diff --git a/src/lib.rs b/src/lib.rs index 3f9401a..f0d1d2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use std::ffi::{c_void, CStr, CString}; - -pub mod pressio { - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} +use std::ffi::{CStr, CString, c_void}; #[derive(Debug, Clone)] pub struct PressioError { @@ -16,9 +12,9 @@ pub struct PressioError { impl From<&Pressio> for PressioError { fn from(library: &Pressio) -> Self { - let error_code = unsafe { pressio::pressio_error_code(library.library) }; + let error_code = unsafe { libpressio_sys::pressio_error_code(library.library) }; let message = unsafe { - let message = pressio::pressio_error_msg(library.library); + let message = libpressio_sys::pressio_error_msg(library.library); CStr::from_ptr(message).to_str() }; match message { @@ -33,9 +29,9 @@ impl From<&Pressio> for PressioError { impl From for PressioError { fn from(library: PressioCompressor) -> Self { - let error_code = unsafe { pressio::pressio_compressor_error_code(library.ptr) }; + let error_code = unsafe { libpressio_sys::pressio_compressor_error_code(library.ptr) }; let message = unsafe { - let message = pressio::pressio_compressor_error_msg(library.ptr); + let message = libpressio_sys::pressio_compressor_error_msg(library.ptr); CStr::from_ptr(message).to_str() }; match message { @@ -49,9 +45,9 @@ impl From for PressioError { } impl From<&PressioCompressor> for PressioError { fn from(library: &PressioCompressor) -> Self { - let error_code = unsafe { pressio::pressio_compressor_error_code(library.ptr) }; + let error_code = unsafe { libpressio_sys::pressio_compressor_error_code(library.ptr) }; let message = unsafe { - let message = pressio::pressio_compressor_error_msg(library.ptr); + let message = libpressio_sys::pressio_compressor_error_msg(library.ptr); CStr::from_ptr(message).to_str() }; match message { @@ -83,11 +79,11 @@ impl From for PressioError { } pub struct Pressio { - library: *mut pressio::pressio, + library: *mut libpressio_sys::pressio, } pub struct PressioCompressor { - ptr: *mut pressio::pressio_compressor, + ptr: *mut libpressio_sys::pressio_compressor, } impl PressioCompressor { pub fn compress( @@ -96,7 +92,11 @@ impl PressioCompressor { compressed_data: PressioData, ) -> Result { let rc = unsafe { - pressio::pressio_compressor_compress(self.ptr, input_data.data, compressed_data.data) + libpressio_sys::pressio_compressor_compress( + self.ptr, + input_data.data, + compressed_data.data, + ) }; if rc == 0 { Ok(compressed_data) @@ -111,7 +111,7 @@ impl PressioCompressor { decompressed_data: PressioData, ) -> Result { let rc = unsafe { - pressio::pressio_compressor_decompress( + libpressio_sys::pressio_compressor_decompress( self.ptr, compressed_data.data, decompressed_data.data, @@ -125,16 +125,12 @@ impl PressioCompressor { } pub fn set_options(&self, options: &PressioOptions) -> Result<(), PressioError> { - let rc = unsafe { pressio::pressio_compressor_set_options(self.ptr, options.ptr) }; - if rc == 0 { - Ok(()) - } else { - Err(self.into()) - } + let rc = unsafe { libpressio_sys::pressio_compressor_set_options(self.ptr, options.ptr) }; + if rc == 0 { Ok(()) } else { Err(self.into()) } } pub fn get_options(&self) -> Result { - let options = unsafe { pressio::pressio_compressor_get_options(self.ptr) }; + let options = unsafe { libpressio_sys::pressio_compressor_get_options(self.ptr) }; if !options.is_null() { Ok(PressioOptions::from_raw(options)) } else { @@ -143,7 +139,7 @@ impl PressioCompressor { } pub fn get_metric_results(&self) -> Result { - let ptr = unsafe { pressio::pressio_compressor_get_metrics_results(self.ptr) }; + let ptr = unsafe { libpressio_sys::pressio_compressor_get_metrics_results(self.ptr) }; if !ptr.is_null() { Ok(PressioOptions::from_raw(ptr)) } else { @@ -155,7 +151,7 @@ impl PressioCompressor { impl Drop for PressioCompressor { fn drop(&mut self) { unsafe { - pressio::pressio_compressor_release(self.ptr); + libpressio_sys::pressio_compressor_release(self.ptr); } } } @@ -163,15 +159,15 @@ impl Drop for PressioCompressor { impl Drop for Pressio { fn drop(&mut self) { unsafe { - pressio::pressio_release(self.library); + libpressio_sys::pressio_release(self.library); } } } impl Pressio { pub fn new() -> Result { - let library: *mut pressio::pressio; + let library: *mut libpressio_sys::pressio; unsafe { - library = pressio::pressio_instance(); + library = libpressio_sys::pressio_instance(); } if !library.is_null() { Ok(Pressio { library }) @@ -185,7 +181,7 @@ impl Pressio { pub fn get_compressor>(&self, id: S) -> Result { let id = CString::new(id.as_ref())?; - let ptr = unsafe { pressio::pressio_get_compressor(self.library, id.as_ptr()) }; + let ptr = unsafe { libpressio_sys::pressio_get_compressor(self.library, id.as_ptr()) }; if !ptr.is_null() { Ok(PressioCompressor { ptr }) } else { @@ -195,14 +191,17 @@ impl Pressio { } pub struct PressioData { - data: *mut pressio::pressio_data, + data: *mut libpressio_sys::pressio_data, } impl PressioData { - pub fn new_empty>(dtype: pressio::pressio_dtype, dims: D) -> PressioData { + pub fn new_empty>( + dtype: libpressio_sys::pressio_dtype, + dims: D, + ) -> PressioData { let dim_arr = dims.as_ref(); let data = unsafe { - pressio::pressio_data_new_empty(dtype, dim_arr.len() as u64, dim_arr.as_ptr()) + libpressio_sys::pressio_data_new_empty(dtype, dim_arr.len(), dim_arr.as_ptr()) }; PressioData { data } } @@ -210,18 +209,18 @@ impl PressioData { impl Clone for PressioData { fn clone(&self) -> PressioData { PressioData { - data: unsafe { pressio::pressio_data_new_clone(self.data) }, + data: unsafe { libpressio_sys::pressio_data_new_clone(self.data) }, } } } impl From> for PressioData { fn from(mut input_array: ndarray::ArrayD) -> Self { let data = unsafe { - pressio::pressio_data_new_copy( - pressio::pressio_dtype_pressio_float_dtype, + libpressio_sys::pressio_data_new_copy( + libpressio_sys::pressio_dtype_pressio_float_dtype, input_array.as_mut_ptr() as *mut c_void, - input_array.ndim() as u64, - input_array.shape().as_ptr() as *const u64, + input_array.ndim(), + input_array.shape().as_ptr(), ) }; PressioData { data } @@ -230,7 +229,7 @@ impl From> for PressioData { impl Drop for PressioData { fn drop(&mut self) { unsafe { - pressio::pressio_data_free(self.data); + libpressio_sys::pressio_data_free(self.data); } } } @@ -254,13 +253,13 @@ pub enum PressioOption { } pub struct PressioOptions { - ptr: *mut pressio::pressio_options, + ptr: *mut libpressio_sys::pressio_options, } impl std::fmt::Display for PressioOptions { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let msg = unsafe { - let ptr = pressio::pressio_options_to_string(self.ptr) ; + let ptr = libpressio_sys::pressio_options_to_string(self.ptr); let s = CStr::from_ptr(ptr).to_str().unwrap().to_string(); libc::free(ptr as *mut c_void); s @@ -271,17 +270,17 @@ impl std::fmt::Display for PressioOptions { impl PressioOptions { pub fn new() -> Result { - let ptr = unsafe { pressio::pressio_options_new() }; + let ptr = unsafe { libpressio_sys::pressio_options_new() }; if !ptr.is_null() { Ok(PressioOptions { ptr }) } else { - Err(PressioError{ + Err(PressioError { message: "failed to allocate options".to_string(), - error_code: 1 + error_code: 1, }) } } - fn from_raw(ptr: *mut pressio::pressio_options) -> PressioOptions { + fn from_raw(ptr: *mut libpressio_sys::pressio_options) -> PressioOptions { PressioOptions { ptr } } @@ -291,43 +290,45 @@ impl PressioOptions { option: PressioOption, ) -> Result { let option_name = option_name.as_ref(); - let option_name = CString::new(option_name)?.as_ptr(); + let option_name = CString::new(option_name)?; + let option_name = option_name.as_ptr(); unsafe { match option { PressioOption::int8(Some(x)) => { - pressio::pressio_options_set_integer8(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_integer8(self.ptr, option_name, x) } PressioOption::int16(Some(x)) => { - pressio::pressio_options_set_integer16(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_integer16(self.ptr, option_name, x) } PressioOption::int32(Some(x)) => { - pressio::pressio_options_set_integer(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_integer(self.ptr, option_name, x) } PressioOption::int64(Some(x)) => { - pressio::pressio_options_set_integer64(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_integer64(self.ptr, option_name, x) } PressioOption::uint8(Some(x)) => { - pressio::pressio_options_set_uinteger8(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_uinteger8(self.ptr, option_name, x) } PressioOption::uint16(Some(x)) => { - pressio::pressio_options_set_uinteger16(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_uinteger16(self.ptr, option_name, x) } PressioOption::uint32(Some(x)) => { - pressio::pressio_options_set_uinteger(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_uinteger(self.ptr, option_name, x) } PressioOption::uint64(Some(x)) => { - pressio::pressio_options_set_uinteger64(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_uinteger64(self.ptr, option_name, x) } PressioOption::float32(Some(x)) => { - pressio::pressio_options_set_float(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_float(self.ptr, option_name, x) } PressioOption::float64(Some(x)) => { - pressio::pressio_options_set_double(self.ptr, option_name, x) + libpressio_sys::pressio_options_set_double(self.ptr, option_name, x) } PressioOption::string(Some(x)) => { - let option_value = CString::new(x)?.as_ptr(); - pressio::pressio_options_set_string(self.ptr, option_name, option_value) + let option_value = CString::new(x)?; + let option_ptr = option_value.as_ptr(); + libpressio_sys::pressio_options_set_string(self.ptr, option_name, option_ptr) } PressioOption::vec_string(Some(x)) => { let option_value = x @@ -336,116 +337,116 @@ impl PressioOptions { .collect::, _>>()?; let option_value_cptr: Vec<*const i8> = option_value.iter().map(|val| val.as_ptr()).collect(); - pressio::pressio_options_set_strings( + libpressio_sys::pressio_options_set_strings( self.ptr, option_name, - option_value_cptr.len() as u64, + option_value_cptr.len(), option_value_cptr.as_ptr(), ); } PressioOption::data(Some(x)) => { - pressio::pressio_options_set_data(self.ptr, option_name, x.data); + libpressio_sys::pressio_options_set_data(self.ptr, option_name, x.data); } PressioOption::user_ptr(Some(x)) => { - pressio::pressio_options_set_userptr(self.ptr, option_name, x); + libpressio_sys::pressio_options_set_userptr(self.ptr, option_name, x); } PressioOption::unset => {} PressioOption::int8(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_option_type_pressio_option_int8_type, + libpressio_sys::pressio_option_type_pressio_option_int8_type, ); } PressioOption::int16(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_int16_dtype, + libpressio_sys::pressio_dtype_pressio_int16_dtype, ); } PressioOption::int32(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_int32_dtype, + libpressio_sys::pressio_dtype_pressio_int32_dtype, ); } PressioOption::int64(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_int64_dtype, + libpressio_sys::pressio_dtype_pressio_int64_dtype, ); } PressioOption::uint8(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint8_dtype, + libpressio_sys::pressio_dtype_pressio_uint8_dtype, ); } PressioOption::uint16(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint16_dtype, + libpressio_sys::pressio_dtype_pressio_uint16_dtype, ); } PressioOption::uint32(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint32_dtype, + libpressio_sys::pressio_dtype_pressio_uint32_dtype, ); } PressioOption::uint64(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint64_dtype, + libpressio_sys::pressio_dtype_pressio_uint64_dtype, ); } PressioOption::float32(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_float_dtype, + libpressio_sys::pressio_dtype_pressio_float_dtype, ); } PressioOption::float64(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_double_dtype, + libpressio_sys::pressio_dtype_pressio_double_dtype, ); } PressioOption::string(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint64_dtype, + libpressio_sys::pressio_dtype_pressio_uint64_dtype, ); } PressioOption::vec_string(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint64_dtype, + libpressio_sys::pressio_dtype_pressio_uint64_dtype, ); } PressioOption::data(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint64_dtype, + libpressio_sys::pressio_dtype_pressio_uint64_dtype, ); } PressioOption::user_ptr(None) => { - pressio::pressio_options_set_type( + libpressio_sys::pressio_options_set_type( self.ptr, option_name, - pressio::pressio_dtype_pressio_uint64_dtype, + libpressio_sys::pressio_dtype_pressio_uint64_dtype, ); } } @@ -456,47 +457,39 @@ impl PressioOptions { impl Drop for PressioOptions { fn drop(&mut self) { unsafe { - pressio::pressio_options_free(self.ptr); + libpressio_sys::pressio_options_free(self.ptr); } } } #[cfg(test)] mod tests { + use super::*; fn input_data() -> ndarray::ArrayD { let data = unsafe { - let mut data = ndarray::Array2::::uninitialized([30, 30]); + let mut data = ndarray::Array2::::uninit([30, 30]); for ((x, y), elm) in data.indexed_iter_mut() { - *elm = (x + y) as f32; + *elm = std::mem::MaybeUninit::new((x + y) as f32); } - data + data.assume_init() }; data.into_dyn() } #[test] fn safe_works() -> Result<(), crate::PressioError> { - use crate::*; let lib = Pressio::new().expect("failed to create library"); - let compressor = lib.get_compressor("sz").expect("expected compressor"); + eprintln!("supported compressors: {:}", unsafe {CStr::from_ptr(libpressio_sys::pressio_supported_compressors()).to_str()?}); + let compressor = lib.get_compressor("pressio").expect("expected compressor"); let options = PressioOptions::new()? - .set( - "sz:error_bound_mode_str", - PressioOption::string(Some("abs".to_string())), - )? - .set( - "sz:abs_err_bound", - PressioOption::float64(Some(1e-6)) - )? - .set( - "sz:metric", - PressioOption::string(Some("size".to_string())) - )?; + .set("pressio:lossless", PressioOption::int32(Some(1)))? + .set("pressio:metric", PressioOption::string(Some("size".to_string())))?; let input_pdata: PressioData = input_data().into(); - let compressed_data = PressioData::new_empty(pressio::pressio_dtype_pressio_byte_dtype, []); + let compressed_data = + PressioData::new_empty(libpressio_sys::pressio_dtype_pressio_byte_dtype, []); let decompressed_data = input_pdata.clone(); compressor.set_options(&options).unwrap(); @@ -518,11 +511,10 @@ mod tests { #[test] fn unsafe_works() { - use crate::pressio::*; - use libc; - use std::ffi::{c_void, CStr, CString}; use std::ptr; + use libpressio_sys::*; + unsafe { let library = pressio_instance(); let compressor_id = CString::new("sz").unwrap(); @@ -533,8 +525,8 @@ mod tests { let input_pdata = pressio_data_new_copy( pressio_dtype_pressio_float_dtype, input_array.as_mut_ptr() as *mut c_void, - input_array.ndim() as u64, - input_array.shape().as_ptr() as *const u64, + input_array.ndim(), + input_array.shape().as_ptr(), ); assert_ne!(input_pdata, ptr::null_mut::()); @@ -543,20 +535,13 @@ mod tests { let output_pdata = pressio_data_new_clone(input_pdata); assert_ne!(output_pdata, ptr::null_mut::()); - let sz_options = pressio_options_new(); - let sz_error_bound_mode_str = CString::new("sz:error_bound_mode_str").unwrap(); - let sz_error_bound_mode = CString::new("abs").unwrap(); - let sz_abs_bound_mode = CString::new("sz:abs_err_bound").unwrap(); - let sz_metric = CString::new("sz:metric").unwrap(); - let sz_metric_value = CString::new("size").unwrap(); - pressio_options_set_string( - sz_options, - sz_error_bound_mode_str.as_ptr(), - sz_error_bound_mode.as_ptr(), - ); - pressio_options_set_string(sz_options, sz_metric.as_ptr(), sz_metric_value.as_ptr()); - pressio_options_set_double(sz_options, sz_abs_bound_mode.as_ptr(), 1e-6); - let ec = pressio_compressor_set_options(compressor, sz_options); + let pressio_options = pressio_options_new(); + let pressio_metric = c"pressio:metric"; + let pressio_metric_value = c"size"; + let pressio_lossless = c"pressio:lossless"; + pressio_options_set_string(pressio_options, pressio_metric.as_ptr(), pressio_metric_value.as_ptr()); + pressio_options_set_integer(pressio_options, pressio_lossless.as_ptr(), 1); + let ec = pressio_compressor_set_options(compressor, pressio_options); assert_eq!(ec, 0); let ec = pressio_compressor_compress(compressor, input_pdata, compressed_pdata); @@ -573,7 +558,7 @@ mod tests { pressio_compressor_release(compressor); pressio_options_free(metrics_results); - pressio_options_free(sz_options); + pressio_options_free(pressio_options); pressio_data_free(input_pdata); pressio_data_free(compressed_pdata); pressio_data_free(output_pdata);