diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 260c673..7958312 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,15 +2,16 @@ name: RocksDB CI on: [push, pull_request] env: - RUST_VERSION: 1.66.0 + RUST_VERSION: 1.75.0 jobs: - fmt: + style: name: Rustfmt runs-on: ubuntu-latest steps: - name: Checkout sources uses: actions/checkout@v2 + - name: Install rust uses: actions-rs/toolchain@v1 with: @@ -18,6 +19,7 @@ jobs: components: rustfmt profile: minimal override: true + - name: Run rustfmt uses: actions-rs/cargo@v1 with: @@ -30,6 +32,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v2 + - name: Install rust uses: actions-rs/toolchain@v1 with: @@ -37,6 +40,7 @@ jobs: components: rust-docs profile: minimal override: true + - name: Run cargo rustdoc uses: actions-rs/cargo@v1 with: @@ -49,6 +53,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v2 + - name: Install rust uses: actions-rs/toolchain@v1 with: @@ -56,6 +61,7 @@ jobs: components: clippy profile: minimal override: true + - name: Run clippy uses: actions-rs/clippy-check@v1 with: @@ -87,6 +93,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v2 + - name: Install rust uses: actions-rs/toolchain@v1 with: @@ -94,18 +101,23 @@ jobs: target: ${{ matrix.target }} profile: minimal override: true + - name: Remove msys64 # Workaround to resolve link error with C:\msys64\mingw64\bin\libclang.dll if: runner.os == 'Windows' run: Remove-Item -LiteralPath "C:\msys64\" -Force -Recurse + - name: Install dependencies if: runner.os == 'Windows' run: choco install llvm -y + - name: Run rocksdb tests run: | cargo test --all cargo test --all --features multi-threaded-cf + - name: Free disk space run: cargo clean + - name: Run rocksdb tests (jemalloc) if: runner.os != 'Windows' run: cargo test --all --features jemalloc diff --git a/Cargo.toml b/Cargo.toml index df23601..dfa0778 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,14 +2,14 @@ name = "rocksdb" description = "Rust wrapper for Facebook's RocksDB embeddable database" version = "0.21.0" -edition = "2018" -rust-version = "1.66.0" +edition = "2021" +rust-version = "1.75.0" authors = ["Tyler Neely ", "David Greenberg "] -repository = "https://github.com/rust-rocksdb/rust-rocksdb" +repository = "https://github.com/zaidoon1/rust-rocksdb" license = "Apache-2.0" categories = [ "database" ] keywords = ["database", "embedded", "LSM-tree", "persistence"] -homepage = "https://github.com/rust-rocksdb/rust-rocksdb" +homepage = "https://github.com/zaidoon1/rust-rocksdb" exclude = [ ".gitignore", ".travis.yml", @@ -40,8 +40,8 @@ librocksdb-sys = { path = "librocksdb-sys", version = "0.16.0" } serde = { version = "1", features = [ "derive" ], optional = true } [dev-dependencies] -trybuild = "1.0" -tempfile = "3.1" -pretty_assertions = "1.0" -bincode = "1.3" +trybuild = "1" +tempfile = "3" +pretty_assertions = "1" +bincode = "1" serde = { version = "1", features = [ "derive" ] } diff --git a/librocksdb-sys/Cargo.toml b/librocksdb-sys/Cargo.toml index e888d28..66f1879 100644 --- a/librocksdb-sys/Cargo.toml +++ b/librocksdb-sys/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "librocksdb-sys" version = "0.16.0+8.10.0" -edition = "2018" -rust-version = "1.66.0" +edition = "2021" +rust-version = "1.75.0" authors = ["Karl Hobley ", "Arkadiy Paronyan "] license = "MIT/Apache-2.0/BSD-3-Clause" description = "Native bindings to librocksdb" @@ -34,7 +34,7 @@ bzip2-sys = { version = "0.1", default-features = false, optional = true } [dev-dependencies] const-cstr = "0.3" -uuid = { version = "1.0", features = ["v4"] } +uuid = { version = "1", features = ["v4"] } [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/src/compaction_filter_factory.rs b/src/compaction_filter_factory.rs index 5895cdb..3855338 100644 --- a/src/compaction_filter_factory.rs +++ b/src/compaction_filter_factory.rs @@ -37,7 +37,7 @@ pub unsafe extern "C" fn name_callback(raw_self: *mut c_void) -> *const c_cha where F: CompactionFilterFactory, { - let self_ = &*(raw_self as *const c_void as *const F); + let self_ = &*(raw_self.cast_const() as *const F); self_.name().as_ptr() } diff --git a/src/db.rs b/src/db.rs index 554fd79..1b37063 100644 --- a/src/db.rs +++ b/src/db.rs @@ -636,7 +636,7 @@ impl DBWithThreadMode { let cfopts: Vec<_> = cfs_v .iter() - .map(|cf| cf.options.inner as *const _) + .map(|cf| cf.options.inner.cast_const()) .collect(); db = Self::open_cf_raw( @@ -1147,7 +1147,7 @@ impl DBCommon { .collect(); let ptr_cfs: Vec<_> = cfs_and_keys .iter() - .map(|(c, _)| c.inner() as *const _) + .map(|(c, _)| c.inner().cast_const()) .collect(); let mut values = vec![ptr::null_mut(); ptr_keys.len()]; @@ -1225,7 +1225,7 @@ impl DBCommon { ); pinned_values .into_iter() - .zip(errors.into_iter()) + .zip(errors) .map(|(v, e)| { if e.is_null() { if v.is_null() { @@ -2000,7 +2000,7 @@ impl DBCommon { self.inner.inner(), cpaths.as_ptr(), paths_v.len(), - opts.inner as *const _ + opts.inner.cast_const() )); Ok(()) } @@ -2019,7 +2019,7 @@ impl DBCommon { cf.inner(), cpaths.as_ptr(), paths_v.len(), - opts.inner as *const _ + opts.inner.cast_const() )); Ok(()) } @@ -2312,8 +2312,8 @@ pub(crate) fn convert_values( ) -> Vec>, Error>> { values .into_iter() - .zip(values_sizes.into_iter()) - .zip(errors.into_iter()) + .zip(values_sizes) + .zip(errors) .map(|((v, s), e)| { if e.is_null() { let value = unsafe { crate::ffi_util::raw_data(v, s) }; diff --git a/src/db_options.rs b/src/db_options.rs index a802e02..dd3ecdd 100644 --- a/src/db_options.rs +++ b/src/db_options.rs @@ -1108,10 +1108,7 @@ impl Options { /// /// Default: empty pub fn set_db_paths(&mut self, paths: &[DBPath]) { - let mut paths: Vec<_> = paths - .iter() - .map(|path| path.inner as *const ffi::rocksdb_dbpath_t) - .collect(); + let mut paths: Vec<_> = paths.iter().map(|path| path.inner.cast_const()).collect(); let num_paths = paths.len(); unsafe { ffi::rocksdb_options_set_db_paths(self.inner, paths.as_mut_ptr(), num_paths); @@ -2495,7 +2492,7 @@ impl Options { unsafe { ffi::rocksdb_options_set_max_bytes_for_level_multiplier_additional( self.inner, - level_values.as_ptr() as *mut c_int, + level_values.as_ptr().cast_mut(), count, ); } diff --git a/src/lib.rs b/src/lib.rs index 0124f83..54907d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,7 @@ // '... may panic' lints. // Too much work to fix. clippy::missing_errors_doc, + clippy::should_panic_without_expect, // False positive: WebSocket clippy::doc_markdown, clippy::missing_safety_doc, diff --git a/src/merge_operator.rs b/src/merge_operator.rs index b52113e..22b0cb7 100644 --- a/src/merge_operator.rs +++ b/src/merge_operator.rs @@ -211,10 +211,7 @@ impl MergeOperands { let len_ptr = (base_len + (spacing_len * index)) as *const size_t; let len = *len_ptr; let ptr = base + (spacing * index); - Some(slice::from_raw_parts( - *(ptr as *const *const u8) as *const u8, - len, - )) + Some(slice::from_raw_parts(*(ptr as *const *const u8), len)) } } } diff --git a/src/prop_name.rs b/src/prop_name.rs index 0c8f717..8a2b513 100644 --- a/src/prop_name.rs +++ b/src/prop_name.rs @@ -17,24 +17,22 @@ impl PropName { /// Panics if the `value` isn’t terminated by a nul byte or contains /// interior nul bytes. pub(crate) const fn new_unwrap(value: &str) -> &Self { - let bytes = if let Some((&0, bytes)) = value.as_bytes().split_last() { - bytes + if let Some((&0, bytes)) = value.as_bytes().split_last() { + let mut idx = 0; + while idx < bytes.len() { + assert!(bytes[idx] != 0, "input contained interior nul byte"); + idx += 1; + } + + // SAFETY: 1. We’ve just verified `value` is a nul-terminated with no + // interior nul bytes and since its `str` it’s also valid UTF-8. + // 2. Self and CStr have the same representation so casting is sound. + unsafe { + let value = CStr::from_bytes_with_nul_unchecked(value.as_bytes()); + &*(value as *const CStr as *const Self) + } } else { panic!("input was not nul-terminated"); - }; - - let mut idx = 0; - while idx < bytes.len() { - assert!(bytes[idx] != 0, "input contained interior nul byte"); - idx += 1; - } - - // SAFETY: 1. We’ve just verified `value` is a nul-terminated with no - // interior nul bytes and since its `str` it’s also valid UTF-8. - // 2. Self and CStr have the same representation so casting is sound. - unsafe { - let value = CStr::from_bytes_with_nul_unchecked(value.as_bytes()); - &*(value as *const CStr as *const Self) } } diff --git a/src/transactions/optimistic_transaction_db.rs b/src/transactions/optimistic_transaction_db.rs index 5642594..27e494f 100644 --- a/src/transactions/optimistic_transaction_db.rs +++ b/src/transactions/optimistic_transaction_db.rs @@ -166,7 +166,7 @@ impl OptimisticTransactionDB { let cfopts: Vec<_> = cfs_v .iter() - .map(|cf| cf.options.inner as *const _) + .map(|cf| cf.options.inner.cast_const()) .collect(); db = Self::open_cf_raw(opts, &cpath, &cfs_v, &cfnames, &cfopts, &mut cfhandles)?; @@ -262,7 +262,7 @@ impl OptimisticTransactionDB { std::ptr::null_mut(), ) }, - _marker: PhantomData::default(), + _marker: PhantomData, } } diff --git a/src/transactions/transaction.rs b/src/transactions/transaction.rs index 089e1ad..f0bc625 100644 --- a/src/transactions/transaction.rs +++ b/src/transactions/transaction.rs @@ -556,7 +556,7 @@ impl<'db, DB> Transaction<'db, DB> { .collect(); let ptr_cfs: Vec<_> = cfs_and_keys .iter() - .map(|(c, _)| c.inner() as *const _) + .map(|(c, _)| c.inner().cast_const()) .collect(); let mut values = vec![ptr::null_mut(); ptr_keys.len()]; diff --git a/src/transactions/transaction_db.rs b/src/transactions/transaction_db.rs index c4f81d8..1806674 100644 --- a/src/transactions/transaction_db.rs +++ b/src/transactions/transaction_db.rs @@ -266,7 +266,7 @@ impl TransactionDB { let cfopts: Vec<_> = cfs_v .iter() - .map(|cf| cf.options.inner as *const _) + .map(|cf| cf.options.inner.cast_const()) .collect(); db = Self::open_cf_raw( @@ -408,7 +408,7 @@ impl TransactionDB { std::ptr::null_mut(), ) }, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -423,7 +423,7 @@ impl TransactionDB { .drain(0..) .map(|inner| Transaction { inner, - _marker: PhantomData::default(), + _marker: PhantomData, }) .collect() } @@ -600,7 +600,7 @@ impl TransactionDB { .collect(); let ptr_cfs: Vec<_> = cfs_and_keys .iter() - .map(|(c, _)| c.inner() as *const _) + .map(|(c, _)| c.inner().cast_const()) .collect(); let mut values = vec![ptr::null_mut(); ptr_keys.len()]; diff --git a/tests/fail/checkpoint_outlive_db.stderr b/tests/fail/checkpoint_outlive_db.stderr index a8ff0cc..6d16fa8 100644 --- a/tests/fail/checkpoint_outlive_db.stderr +++ b/tests/fail/checkpoint_outlive_db.stderr @@ -4,6 +4,7 @@ error[E0597]: `db` does not live long enough 4 | let _checkpoint = { | ----------- borrow later stored here 5 | let db = DB::open_default("foo").unwrap(); + | -- binding `db` declared here 6 | Checkpoint::new(&db) | ^^^ borrowed value does not live long enough 7 | }; diff --git a/tests/fail/iterator_outlive_db.stderr b/tests/fail/iterator_outlive_db.stderr index 9fbaf15..ec44728 100644 --- a/tests/fail/iterator_outlive_db.stderr +++ b/tests/fail/iterator_outlive_db.stderr @@ -4,7 +4,8 @@ error[E0597]: `db` does not live long enough 4 | let _iter = { | ----- borrow later stored here 5 | let db = DB::open_default("foo").unwrap(); + | -- binding `db` declared here 6 | db.iterator(IteratorMode::Start) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough 7 | }; | - `db` dropped here while still borrowed diff --git a/tests/fail/open_with_multiple_refs_as_single_threaded.stderr b/tests/fail/open_with_multiple_refs_as_single_threaded.stderr index 0f17e9d..0f573cc 100644 --- a/tests/fail/open_with_multiple_refs_as_single_threaded.stderr +++ b/tests/fail/open_with_multiple_refs_as_single_threaded.stderr @@ -1,17 +1,21 @@ error[E0596]: cannot borrow `*db_ref1` as mutable, as it is behind a `&` reference --> tests/fail/open_with_multiple_refs_as_single_threaded.rs:8:5 | -5 | let db_ref1 = &db; - | --- help: consider changing this to be a mutable reference: `&mut db` -... 8 | db_ref1.create_cf("cf1", &opts).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `db_ref1` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^ `db_ref1` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +5 | let db_ref1 = &mut db; + | +++ error[E0596]: cannot borrow `*db_ref2` as mutable, as it is behind a `&` reference --> tests/fail/open_with_multiple_refs_as_single_threaded.rs:9:5 | -6 | let db_ref2 = &db; - | --- help: consider changing this to be a mutable reference: `&mut db` -... 9 | db_ref2.create_cf("cf2", &opts).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `db_ref2` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^ `db_ref2` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +6 | let db_ref2 = &mut db; + | +++ diff --git a/tests/fail/snapshot_outlive_db.stderr b/tests/fail/snapshot_outlive_db.stderr index e0ae012..097e064 100644 --- a/tests/fail/snapshot_outlive_db.stderr +++ b/tests/fail/snapshot_outlive_db.stderr @@ -4,7 +4,8 @@ error[E0597]: `db` does not live long enough 4 | let _snapshot = { | --------- borrow later stored here 5 | let db = DB::open_default("foo").unwrap(); + | -- binding `db` declared here 6 | db.snapshot() - | ^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough 7 | }; | - `db` dropped here while still borrowed diff --git a/tests/fail/snapshot_outlive_transaction.stderr b/tests/fail/snapshot_outlive_transaction.stderr index 653c1a8..bdcd56c 100644 --- a/tests/fail/snapshot_outlive_transaction.stderr +++ b/tests/fail/snapshot_outlive_transaction.stderr @@ -4,7 +4,8 @@ error[E0597]: `txn` does not live long enough 5 | let _snapshot = { | --------- borrow later stored here 6 | let txn = db.transaction(); + | --- binding `txn` declared here 7 | txn.snapshot() - | ^^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^^ borrowed value does not live long enough 8 | }; | - `txn` dropped here while still borrowed diff --git a/tests/fail/snapshot_outlive_transaction_db.stderr b/tests/fail/snapshot_outlive_transaction_db.stderr index d07341f..1f2596a 100644 --- a/tests/fail/snapshot_outlive_transaction_db.stderr +++ b/tests/fail/snapshot_outlive_transaction_db.stderr @@ -4,7 +4,8 @@ error[E0597]: `db` does not live long enough 4 | let _snapshot = { | --------- borrow later stored here 5 | let db = TransactionDB::::open_default("foo").unwrap(); + | -- binding `db` declared here 6 | db.snapshot() - | ^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough 7 | }; | - `db` dropped here while still borrowed diff --git a/tests/fail/transaction_outlive_transaction_db.stderr b/tests/fail/transaction_outlive_transaction_db.stderr index 45237a3..edf8155 100644 --- a/tests/fail/transaction_outlive_transaction_db.stderr +++ b/tests/fail/transaction_outlive_transaction_db.stderr @@ -4,7 +4,8 @@ error[E0597]: `db` does not live long enough 4 | let _txn = { | ---- borrow later stored here 5 | let db = TransactionDB::::open_default("foo").unwrap(); + | -- binding `db` declared here 6 | db.transaction() - | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough 7 | }; | - `db` dropped here while still borrowed diff --git a/tests/test_backup.rs b/tests/test_backup.rs index b1dff2e..8de97b1 100644 --- a/tests/test_backup.rs +++ b/tests/test_backup.rs @@ -90,7 +90,7 @@ fn restore_from_backup() { assert!(i.size > 0); }); - let backup_id = info.get(0).unwrap().backup_id; + let backup_id = info.first().unwrap().backup_id; let mut restore_option = RestoreOptions::default(); restore_option.set_keep_log_files(false); // true to keep log files let restore_status = backup_engine.restore_from_backup( diff --git a/tests/test_transaction_db.rs b/tests/test_transaction_db.rs index 2deb3dc..901b7ec 100644 --- a/tests/test_transaction_db.rs +++ b/tests/test_transaction_db.rs @@ -659,7 +659,7 @@ fn two_phase_commit() { let txns = db.prepared_transactions(); assert_eq!(txns.len(), 2); - for (_, txn) in txns.into_iter().enumerate() { + for txn in txns.into_iter() { let name = txn.get_name().unwrap(); if name == b"t1" {