From 7c707793a75a7d2e2c7f98005bc98aff3a0c125c Mon Sep 17 00:00:00 2001 From: simonsan <14062932+simonsan@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:27:46 +0100 Subject: [PATCH 1/2] chore: update to 2021 edition and implement clippy fixes Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com> --- Cargo.toml | 2 +- build.rs | 2 +- native_db_macro/src/keys.rs | 11 +- native_db_macro/src/model_attributes.rs | 8 +- src/database.rs | 29 ++--- src/database_builder.rs | 23 ++-- src/db_type/input.rs | 8 +- src/db_type/key/inner_key_value.rs | 111 ++++++++---------- src/db_type/key/key_definition.rs | 6 +- src/db_type/output.rs | 17 +-- src/lib.rs | 54 +++++++++ src/model.rs | 13 +- src/snapshot.rs | 9 +- src/table_definition.rs | 20 +--- .../internal/private_readable_transaction.rs | 6 +- src/transaction/internal/r_transaction.rs | 9 +- src/transaction/internal/rw_transaction.rs | 51 ++++---- src/transaction/query/drain.rs | 7 +- src/transaction/query/scan/primary_scan.rs | 17 +-- src/transaction/query/scan/secondary_scan.rs | 25 ++-- src/transaction/r_transaction.rs | 6 +- src/transaction/rw_transaction.rs | 20 ++-- src/watch/batch.rs | 4 +- src/watch/event.rs | 18 +-- src/watch/filter.rs | 19 +-- src/watch/mod.rs | 17 +-- src/watch/query/internal.rs | 20 ++-- src/watch/query/mod.rs | 4 +- src/watch/query/scan.rs | 10 +- src/watch/request.rs | 2 +- src/watch/sender.rs | 24 ++-- tests/custom_type/chrono.rs | 2 +- tests/custom_type/uuid.rs | 2 +- tests/macro_def/secondary_key.rs | 8 +- tests/native_model.rs | 1 - tests/scan.rs | 4 +- tests/watch_tokio.rs | 2 +- 37 files changed, 301 insertions(+), 290 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2488bb7..6775a45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "native_db" version = "0.5.1" authors = ["Vincent Herlemont "] -edition = "2018" +edition = "2021" description = "Drop-in embedded database" license = "MIT" repository = "https://github.com/vincent-herlemont/native_db" diff --git a/build.rs b/build.rs index 94769f7..c4d74f8 100644 --- a/build.rs +++ b/build.rs @@ -5,4 +5,4 @@ fn main() { // Run skeptic skeptic::generate_doc_tests(&["README.md"]); } -} \ No newline at end of file +} diff --git a/native_db_macro/src/keys.rs b/native_db_macro/src/keys.rs index ec89a77..6e81308 100644 --- a/native_db_macro/src/keys.rs +++ b/native_db_macro/src/keys.rs @@ -37,7 +37,7 @@ impl ToTokenStream for DatabaseKeyDefinition { } } -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct DatabaseSecondaryKeyOptions { pub(crate) unique: bool, pub(crate) optional: bool, @@ -62,15 +62,6 @@ impl ToTokenStream for () { } } -impl Default for DatabaseSecondaryKeyOptions { - fn default() -> Self { - Self { - unique: false, - optional: false, - } - } -} - impl DatabaseKeyDefinition { pub(crate) fn name(&self) -> String { if let Some(field_name) = &self.field_name { diff --git a/native_db_macro/src/model_attributes.rs b/native_db_macro/src/model_attributes.rs index a656488..b29d55e 100644 --- a/native_db_macro/src/model_attributes.rs +++ b/native_db_macro/src/model_attributes.rs @@ -27,7 +27,7 @@ impl ModelAttributes { } else { panic!( "Unknown attribute: {}", - meta.path.get_ident().unwrap().to_string() + meta.path.get_ident().unwrap() ); } Ok(()) @@ -46,7 +46,7 @@ impl ModelAttributes { } else { panic!( "Unknown attribute: {}", - meta.path.get_ident().unwrap().to_string() + meta.path.get_ident().unwrap() ); } Ok(()) @@ -55,7 +55,7 @@ impl ModelAttributes { } else { panic!( "Unknown attribute: {}", - meta.path.get_ident().unwrap().to_string() + meta.path.get_ident().unwrap() ); } Ok(()) @@ -71,7 +71,7 @@ impl ModelAttributes { )); } else if attr.path().is_ident("secondary_key") { let mut secondary_options = DatabaseSecondaryKeyOptions::default(); - if let Ok(_) = attr.meta.require_list() { + if attr.meta.require_list().is_ok() { attr.parse_nested_meta(|meta| { if meta.path.is_ident("unique") { secondary_options.unique = true; diff --git a/src/database.rs b/src/database.rs index c0b1bae..6717dd8 100644 --- a/src/database.rs +++ b/src/database.rs @@ -15,7 +15,7 @@ use std::sync::atomic::AtomicU64; use std::sync::{Arc, RwLock}; use std::u64; -/// The database instance. Allows you to create [rw_transaction](database/struct.Database.html#method.rw_transaction) and [r_transaction](database/struct.Database.html#method.r_transaction), [watch](database/struct.Database.html#method.watch) queries, and [unwatch](database/struct.Database.html#method.unwatch) etc. +/// The database instance. Allows you to create [`rw_transaction`](database/struct.Database.html#method.rw_transaction) and [`r_transaction`](database/struct.Database.html#method.r_transaction), [watch](database/struct.Database.html#method.watch) queries, and [unwatch](database/struct.Database.html#method.unwatch) etc. /// /// # Example /// ```rust @@ -40,7 +40,7 @@ pub struct Database<'a> { impl Database<'_> { /// Creates a new read-write transaction. - pub fn rw_transaction(&self) -> Result { + pub fn rw_transaction(&self) -> Result> { let rw = self.instance.begin_write()?; let write_txn = RwTransaction { watcher: &self.watchers, @@ -54,7 +54,7 @@ impl Database<'_> { } /// Creates a new read-only transaction. - pub fn r_transaction(&self) -> Result { + pub fn r_transaction(&self) -> Result> { let txn = self.instance.begin_read()?; let read_txn = RTransaction { internal: InternalRTransaction { @@ -68,7 +68,7 @@ impl Database<'_> { impl Database<'_> { /// Watch queries. - pub fn watch(&self) -> Watch { + pub const fn watch(&self) -> Watch<'_> { Watch { internal: InternalWatch { watchers: &self.watchers, @@ -82,8 +82,7 @@ impl Database<'_> { /// If the `id` is not valid anymore, this function will do nothing. /// If the `id` is valid, the corresponding watcher will be removed. pub fn unwatch(&self, id: u64) -> Result<()> { - let mut watchers = self.watchers.write().unwrap(); - watchers.remove_sender(id); + self.watchers.write().unwrap().remove_sender(id); Ok(()) } } @@ -92,26 +91,22 @@ impl<'a> Database<'a> { pub(crate) fn seed_model(&mut self, model_builder: &'a ModelBuilder) -> Result<()> { let main_table_definition = redb::TableDefinition::new(model_builder.model.primary_key.unique_table_name.as_str()); - let mut primary_table_definition: PrimaryTableDefinition = + let mut primary_table_definition: PrimaryTableDefinition<'_> = (model_builder, main_table_definition).into(); let rw = self.instance.begin_write()?; - rw.open_table(primary_table_definition.redb.clone())?; + _ = rw.open_table(primary_table_definition.redb)?; for secondary_key in model_builder.model.secondary_keys.iter() { - primary_table_definition.secondary_tables.insert( + _ = primary_table_definition.secondary_tables.insert( secondary_key.clone(), redb::TableDefinition::new(secondary_key.unique_table_name.as_str()).into(), ); - rw.open_table( - primary_table_definition.secondary_tables[&secondary_key] - .redb - .clone(), - )?; + _ = rw.open_table(primary_table_definition.secondary_tables[&secondary_key].redb)?; } rw.commit()?; - self.primary_table_definitions.insert( + _ = self.primary_table_definitions.insert( model_builder.model.primary_key.unique_table_name.clone(), primary_table_definition, ); @@ -124,7 +119,7 @@ impl<'a> Database<'a> { let rx = self.instance.begin_read()?; let mut stats_primary_tables = vec![]; for primary_table in self.primary_table_definitions.values() { - let result_table_open = rx.open_table(primary_table.redb.clone()); + let result_table_open = rx.open_table(primary_table.redb); let stats_table = match result_table_open { Err(redb::TableError::TableDoesNotExist(_)) => StatsTable { name: primary_table.redb.name().to_string(), @@ -146,7 +141,7 @@ impl<'a> Database<'a> { let mut stats_secondary_tables = vec![]; for primary_table in self.primary_table_definitions.values() { for secondary_table in primary_table.secondary_tables.values() { - let result_table_open = rx.open_table(secondary_table.redb.clone()); + let result_table_open = rx.open_table(secondary_table.redb); let stats_table = match result_table_open { Err(redb::TableError::TableDoesNotExist(_)) => StatsTable { name: secondary_table.redb.name().to_string(), diff --git a/src/database_builder.rs b/src/database_builder.rs index d92f1c2..8203edb 100644 --- a/src/database_builder.rs +++ b/src/database_builder.rs @@ -7,6 +7,7 @@ use std::sync::atomic::AtomicU64; use std::sync::{Arc, RwLock}; /// Builder that allows you to create a [`Database`](crate::Database) instance via [`create`](Self::create) or [`open`](Self::open) etc. and [define](Self::define) models. +#[derive(Default)] pub struct DatabaseBuilder { cache_size_bytes: Option, models_builder: HashMap, @@ -16,12 +17,12 @@ impl DatabaseBuilder { fn new_rdb_builder(&self) -> redb::Builder { let mut redb_builder = redb::Builder::new(); if let Some(cache_size_bytes) = self.cache_size_bytes { - redb_builder.set_cache_size(cache_size_bytes); + _ = redb_builder.set_cache_size(cache_size_bytes); } redb_builder } - fn init<'a>(&'a self, redb_database: redb::Database) -> Result> { + fn init(&self, redb_database: redb::Database) -> Result> { let mut database = Database { instance: redb_database, primary_table_definitions: HashMap::new(), @@ -29,8 +30,8 @@ impl DatabaseBuilder { watchers_counter_id: AtomicU64::new(0), }; - for (_, model_builder) in &self.models_builder { - database.seed_model(&model_builder)?; + for model_builder in self.models_builder.values() { + database.seed_model(model_builder)?; } Ok(database) @@ -55,21 +56,21 @@ impl DatabaseBuilder { /// Creates a new `Db` instance using the given path. /// /// Similar to [redb::Builder.create(...)](https://docs.rs/redb/latest/redb/struct.Builder.html#method.create) - pub fn create(&self, path: impl AsRef) -> Result { + pub fn create(&self, path: impl AsRef) -> Result> { let db = self.new_rdb_builder().create(path)?; // Ok(Self::from_redb(db)) self.init(db) } /// Similar to [redb::Builder::open(...)](https://docs.rs/redb/latest/redb/struct.Builder.html#method.open) - pub fn open(&self, path: impl AsRef) -> Result { + pub fn open(&self, path: impl AsRef) -> Result> { let db = self.new_rdb_builder().open(path)?; // Ok(Self::from_redb(db)) self.init(db) } /// Creates a new [`Database`](crate::Database) instance in memory. - pub fn create_in_memory(&self) -> Result { + pub fn create_in_memory(&self) -> Result> { let in_memory_backend = redb::backends::InMemoryBackend::new(); let db = self.new_rdb_builder(); let db = db.create_with_backend(in_memory_backend)?; @@ -299,7 +300,7 @@ impl DatabaseBuilder { } } - self.models_builder.insert( + _ = self.models_builder.insert( new_model_builder .model .primary_key @@ -321,7 +322,7 @@ impl DatabaseBuilder { } } -pub(crate) struct ModelBuilder { - pub(crate) model: DatabaseModel, - pub(crate) native_model_options: NativeModelOptions, +pub struct ModelBuilder { + pub model: DatabaseModel, + pub native_model_options: NativeModelOptions, } diff --git a/src/db_type/input.rs b/src/db_type/input.rs index 9e484c1..27e570b 100644 --- a/src/db_type/input.rs +++ b/src/db_type/input.rs @@ -20,11 +20,13 @@ impl DatabaseInput { ) -> Result { let secondary_key = self.secondary_keys.get(secondary_key_def).ok_or( Error::SecondaryKeyDefinitionNotFound { - table: "".to_string(), + table: String::new(), key: secondary_key_def.unique_table_name.clone(), }, )?; - let out = if !secondary_key_def.options.unique { + let out = if secondary_key_def.options.unique { + secondary_key.clone() + } else { match secondary_key { DatabaseKeyValue::Default(value) => { DatabaseKeyValue::Default(composite_key(value, &self.primary_key)) @@ -36,8 +38,6 @@ impl DatabaseInput { DatabaseKeyValue::Optional(value) } } - } else { - secondary_key.clone() }; Ok(out) } diff --git a/src/db_type/key/inner_key_value.rs b/src/db_type/key/inner_key_value.rs index 4c8cfef..2f7fd4c 100644 --- a/src/db_type/key/inner_key_value.rs +++ b/src/db_type/key/inner_key_value.rs @@ -10,7 +10,7 @@ impl DatabaseInnerKeyValue { Self(data) } - pub(crate) fn extend(&mut self, data: &DatabaseInnerKeyValue) { + pub(crate) fn extend(&mut self, data: &Self) { self.0.extend(data.0.iter()); } @@ -186,10 +186,10 @@ where T: InnerKeyValue, { fn database_inner_key_value(&self) -> DatabaseInnerKeyValue { - match self { - Some(value) => value.database_inner_key_value(), - None => DatabaseInnerKeyValue::new(Vec::new()), - } + self.as_ref().map_or_else( + || DatabaseInnerKeyValue::new(Vec::new()), + |value| value.database_inner_key_value(), + ) } } @@ -256,7 +256,7 @@ where } impl RedbValue for DatabaseInnerKeyValue { - type SelfType<'a> = DatabaseInnerKeyValue; + type SelfType<'a> = Self; type AsBytes<'a> = &'a [u8] where Self: 'a; fn fixed_width() -> Option { @@ -272,8 +272,7 @@ impl RedbValue for DatabaseInnerKeyValue { fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a> where - Self: 'a, - Self: 'b, + Self: 'a + 'b, { value.0.as_slice() } @@ -285,10 +284,11 @@ impl RedbValue for DatabaseInnerKeyValue { impl RedbKey for DatabaseInnerKeyValue { fn compare(data1: &[u8], data2: &[u8]) -> std::cmp::Ordering { - data1.cmp(&data2) + data1.cmp(data2) } } +#[derive(Debug)] pub enum DatabaseInnerKeyValueRange { Range(Range), RangeInclusive(RangeInclusive), @@ -299,48 +299,38 @@ pub enum DatabaseInnerKeyValueRange { } impl DatabaseInnerKeyValueRange { - pub fn new(bounds: impl RangeBounds) -> DatabaseInnerKeyValueRange + pub fn new(bounds: impl RangeBounds) -> Self where T: InnerKeyValue, { + // FIXME: Here are a lot of match arms with identical bodies to another arm + // this needs to be refactored match (bounds.start_bound(), bounds.end_bound()) { - (Bound::Included(start), Bound::Included(end)) => { - DatabaseInnerKeyValueRange::RangeInclusive( - start.database_inner_key_value()..=end.database_inner_key_value(), - ) - } - (Bound::Included(start), Bound::Excluded(end)) => DatabaseInnerKeyValueRange::Range( - start.database_inner_key_value()..end.database_inner_key_value(), + (Bound::Included(start), Bound::Included(end)) => Self::RangeInclusive( + start.database_inner_key_value()..=end.database_inner_key_value(), ), - (Bound::Included(start), Bound::Unbounded) => { - DatabaseInnerKeyValueRange::RangeFrom(RangeFrom { - start: start.database_inner_key_value(), - }) + (Bound::Included(start), Bound::Excluded(end)) => { + Self::Range(start.database_inner_key_value()..end.database_inner_key_value()) } - (Bound::Excluded(start), Bound::Included(end)) => { - DatabaseInnerKeyValueRange::RangeInclusive( - start.database_inner_key_value()..=end.database_inner_key_value(), - ) - } - (Bound::Excluded(start), Bound::Excluded(end)) => DatabaseInnerKeyValueRange::Range( - start.database_inner_key_value()..end.database_inner_key_value(), + (Bound::Included(start), Bound::Unbounded) => Self::RangeFrom(RangeFrom { + start: start.database_inner_key_value(), + }), + (Bound::Excluded(start), Bound::Included(end)) => Self::RangeInclusive( + start.database_inner_key_value()..=end.database_inner_key_value(), ), - (Bound::Excluded(start), Bound::Unbounded) => { - DatabaseInnerKeyValueRange::RangeFrom(RangeFrom { - start: start.database_inner_key_value(), - }) - } - (Bound::Unbounded, Bound::Included(end)) => { - DatabaseInnerKeyValueRange::RangeTo(RangeTo { - end: { end.database_inner_key_value() }, - }) - } - (Bound::Unbounded, Bound::Excluded(end)) => { - DatabaseInnerKeyValueRange::RangeTo(RangeTo { - end: end.database_inner_key_value(), - }) + (Bound::Excluded(start), Bound::Excluded(end)) => { + Self::Range(start.database_inner_key_value()..end.database_inner_key_value()) } - (Bound::Unbounded, Bound::Unbounded) => DatabaseInnerKeyValueRange::RangeFull, + (Bound::Excluded(start), Bound::Unbounded) => Self::RangeFrom(RangeFrom { + start: start.database_inner_key_value(), + }), + (Bound::Unbounded, Bound::Included(end)) => Self::RangeTo(RangeTo { + end: { end.database_inner_key_value() }, + }), + (Bound::Unbounded, Bound::Excluded(end)) => Self::RangeTo(RangeTo { + end: end.database_inner_key_value(), + }), + (Bound::Unbounded, Bound::Unbounded) => Self::RangeFull, } } } @@ -348,23 +338,23 @@ impl DatabaseInnerKeyValueRange { impl RangeBounds for DatabaseInnerKeyValueRange { fn start_bound(&self) -> Bound<&DatabaseInnerKeyValue> { match self { - DatabaseInnerKeyValueRange::Range(range) => range.start_bound(), - DatabaseInnerKeyValueRange::RangeInclusive(range) => range.start_bound(), - DatabaseInnerKeyValueRange::RangeFrom(range) => range.start_bound(), - DatabaseInnerKeyValueRange::RangeTo(range) => range.start_bound(), - DatabaseInnerKeyValueRange::RangeToInclusive(range) => range.start_bound(), - DatabaseInnerKeyValueRange::RangeFull => Bound::Unbounded, + Self::Range(range) => range.start_bound(), + Self::RangeInclusive(range) => range.start_bound(), + Self::RangeFrom(range) => range.start_bound(), + Self::RangeTo(range) => range.start_bound(), + Self::RangeToInclusive(range) => range.start_bound(), + Self::RangeFull => Bound::Unbounded, } } fn end_bound(&self) -> Bound<&DatabaseInnerKeyValue> { match self { - DatabaseInnerKeyValueRange::Range(range) => range.end_bound(), - DatabaseInnerKeyValueRange::RangeInclusive(range) => range.end_bound(), - DatabaseInnerKeyValueRange::RangeFrom(range) => range.end_bound(), - DatabaseInnerKeyValueRange::RangeTo(range) => range.end_bound(), - DatabaseInnerKeyValueRange::RangeToInclusive(range) => range.end_bound(), - DatabaseInnerKeyValueRange::RangeFull => Bound::Unbounded, + Self::Range(range) => range.end_bound(), + Self::RangeInclusive(range) => range.end_bound(), + Self::RangeFrom(range) => range.end_bound(), + Self::RangeTo(range) => range.end_bound(), + Self::RangeToInclusive(range) => range.end_bound(), + Self::RangeFull => Bound::Unbounded, } } } @@ -375,15 +365,15 @@ mod tests { use std::ops::RangeBounds; fn range>(range: R) -> DatabaseInnerKeyValueRange { - let range = DatabaseInnerKeyValueRange::new(range); - range + DatabaseInnerKeyValueRange::new(range) } #[test] fn test_range() { use redb::{ReadableTable, TableDefinition}; - const TABLE: TableDefinition = TableDefinition::new("my_data"); + const TABLE: TableDefinition<'_, DatabaseInnerKeyValue, u64> = + TableDefinition::new("my_data"); let backend = redb::backends::InMemoryBackend::new(); let db = redb::Database::builder() @@ -392,7 +382,7 @@ mod tests { let write_txn = db.begin_write().unwrap(); { let mut table = write_txn.open_table(TABLE).unwrap(); - table.insert(0u32.database_inner_key_value(), &123).unwrap(); + _ = table.insert(0u32.database_inner_key_value(), &123).unwrap(); } write_txn.commit().unwrap(); @@ -409,7 +399,6 @@ mod tests { let range = range(0..2); let iter = table.range::(range).unwrap(); - let result: Vec<_> = iter.collect(); - assert_eq!(result.len(), 1); + assert_eq!(iter.count(), 1); } } diff --git a/src/db_type/key/key_definition.rs b/src/db_type/key/key_definition.rs index 3bd89b1..d11b43b 100644 --- a/src/db_type/key/key_definition.rs +++ b/src/db_type/key/key_definition.rs @@ -12,7 +12,7 @@ pub struct DatabaseKeyDefinition { } impl KeyDefinition for DatabaseKeyDefinition { - fn database_key(&self) -> DatabaseKeyDefinition { + fn database_key(&self) -> Self { self.clone() } } @@ -26,7 +26,7 @@ impl DatabaseKeyDefinition { } } - pub fn options(&self) -> &O { + pub const fn options(&self) -> &O { &self.options } } @@ -57,7 +57,7 @@ impl Hash for DatabaseKeyDefinition { } } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct DatabaseSecondaryKeyOptions { pub unique: bool, pub optional: bool, diff --git a/src/db_type/output.rs b/src/db_type/output.rs index 4b6aa27..d1254a6 100644 --- a/src/db_type/output.rs +++ b/src/db_type/output.rs @@ -15,12 +15,13 @@ impl DatabaseOutputValue { } } -pub(crate) fn unwrap_item(item: Option>) -> Option { - if let Some(item) = item { - let item = item.value(); - let item = T::native_db_bincode_decode_from_slice(item); - Some(item) - } else { - None - } +pub fn unwrap_item(item: Option>) -> Option { + item.map_or_else( + || None, + |item| { + let item = item.value(); + let item = T::native_db_bincode_decode_from_slice(item); + Some(item) + }, + ) } diff --git a/src/lib.rs b/src/lib.rs index 6030e19..d7b4563 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,60 @@ //! It supports multiple indexes, real-time watch with filters, model migration, hot snapshot, and more. //! //! See [README.md](https://github.com/vincent-herlemont/native_db) for more information. + +#![allow(dead_code)] +#![forbid(unsafe_code)] +#![warn( + // TODO: frequently check + // unreachable_pub, + // TODO: Activate if you're feeling like fixing stuff + // clippy::pedantic, + // clippy::correctness, + // clippy::suspicious, + // clippy::complexity, + // clippy::perf, + // TODO: Fix documentation + // missing_docs, + // TODO: Implement or derive Debug + // missing_debug_implementations, + rust_2018_idioms, + trivial_casts, + unused_lifetimes, + unused_qualifications, + clippy::nursery, + bad_style, + dead_code, + improper_ctypes, + missing_copy_implementations, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + trivial_numeric_casts, + unused_results, + trivial_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true, + clippy::cast_lossless, + clippy::default_trait_access, + clippy::doc_markdown, + clippy::manual_string_new, + clippy::match_same_arms, + clippy::semicolon_if_nothing_returned, + clippy::trivially_copy_pass_by_ref +)] +#![allow(clippy::type_complexity)] +// FIXME! +#![allow(clippy::match_same_arms)] + mod database; mod database_builder; pub mod db_type; diff --git a/src/model.rs b/src/model.rs index 807142a..d835dbb 100644 --- a/src/model.rs +++ b/src/model.rs @@ -16,21 +16,20 @@ impl DatabaseModel { where F: Fn(DatabaseSecondaryKeyOptions) -> bool, { - let key = self - .secondary_keys - .get(secondary_key.into()) - .ok_or_else(|| Error::SecondaryKeyDefinitionNotFound { + let key = self.secondary_keys.get(secondary_key).ok_or_else(|| { + Error::SecondaryKeyDefinitionNotFound { table: self.primary_key.unique_table_name.to_string(), key: secondary_key.unique_table_name.clone(), - })?; + } + })?; - if check(key.options.clone()) { + if check(key.options) { Ok(()) } else { Err(Error::SecondaryKeyConstraintMismatch { table: self.primary_key.unique_table_name.to_string(), key: secondary_key.unique_table_name.clone(), - got: key.options.clone(), + got: key.options, }) } } diff --git a/src/snapshot.rs b/src/snapshot.rs index 56ec9ca..ec1b1a6 100644 --- a/src/snapshot.rs +++ b/src/snapshot.rs @@ -11,21 +11,22 @@ impl Database<'_> { let w = new_db.instance.begin_write()?; { // Copy primary tables - for (_, primary_table_definition) in &self.primary_table_definitions { + for primary_table_definition in self.primary_table_definitions.values() { let table = r.open_table(primary_table_definition.redb)?; let mut new_table = w.open_table(primary_table_definition.redb)?; for result in table.iter()? { let (key, value) = result?; - new_table.insert(key.value(), value.value())?; + _ = new_table.insert(key.value(), value.value())?; } // Copy secondary tables - for (_, secondary_table_definition) in &primary_table_definition.secondary_tables { + for secondary_table_definition in primary_table_definition.secondary_tables.values() + { let table = r.open_table(secondary_table_definition.redb)?; let mut new_table = w.open_table(secondary_table_definition.redb)?; for result in table.iter()? { let (key, value) = result?; - new_table.insert(key.value(), value.value())?; + _ = new_table.insert(key.value(), value.value())?; } } } diff --git a/src/table_definition.rs b/src/table_definition.rs index 11f1bf9..569c9c3 100644 --- a/src/table_definition.rs +++ b/src/table_definition.rs @@ -3,9 +3,9 @@ use crate::db_type::{DatabaseInnerKeyValue, DatabaseKeyDefinition, DatabaseSecon use std::collections::HashMap; use std::fmt::Debug; -pub(crate) type RedbPrimaryTableDefinition<'a> = +pub type RedbPrimaryTableDefinition<'a> = redb::TableDefinition<'a, DatabaseInnerKeyValue, &'static [u8]>; -pub(crate) type RedbSecondaryTableDefinition<'a> = +pub type RedbSecondaryTableDefinition<'a> = redb::TableDefinition<'a, DatabaseInnerKeyValue, DatabaseInnerKeyValue>; pub struct PrimaryTableDefinition<'a> { @@ -16,7 +16,7 @@ pub struct PrimaryTableDefinition<'a> { pub(crate) native_model_options: NativeModelOptions, } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug, Default)] pub struct NativeModelOptions { pub(crate) native_model_id: u32, pub(crate) native_model_version: u32, @@ -26,16 +26,6 @@ pub struct NativeModelOptions { pub(crate) native_model_legacy: bool, } -impl Default for NativeModelOptions { - fn default() -> Self { - Self { - native_model_id: 0, - native_model_version: 0, - native_model_legacy: false, - } - } -} - impl<'a> From<(&ModelBuilder, RedbPrimaryTableDefinition<'a>)> for PrimaryTableDefinition<'a> { fn from(input: (&ModelBuilder, RedbPrimaryTableDefinition<'a>)) -> Self { let (builder, redb) = input; @@ -43,7 +33,7 @@ impl<'a> From<(&ModelBuilder, RedbPrimaryTableDefinition<'a>)> for PrimaryTableD model: builder.model.clone(), redb, secondary_tables: HashMap::new(), - native_model_options: builder.native_model_options.clone(), + native_model_options: builder.native_model_options, } } } @@ -64,7 +54,7 @@ impl Debug for PrimaryTableDefinition<'_> { } #[derive(Clone)] -pub(crate) struct SecondaryTableDefinition<'a> { +pub struct SecondaryTableDefinition<'a> { pub(crate) redb: RedbSecondaryTableDefinition<'a>, } diff --git a/src/transaction/internal/private_readable_transaction.rs b/src/transaction/internal/private_readable_transaction.rs index 9318196..1f90008 100644 --- a/src/transaction/internal/private_readable_transaction.rs +++ b/src/transaction/internal/private_readable_transaction.rs @@ -15,7 +15,7 @@ pub trait PrivateReadableTransaction<'db, 'txn> { where Self: 'db_bis; - fn table_definitions(&self) -> &HashMap; + fn table_definitions(&self) -> &HashMap>; fn get_primary_table(&'txn self, model: &DatabaseModel) -> Result; @@ -44,13 +44,13 @@ pub trait PrivateReadableTransaction<'db, 'txn> { ) -> Result> { let secondary_key = key_def.database_key(); // Provide a better error for the test of unicity of the secondary key - model.check_secondary_options(&secondary_key, |options| options.unique == true)?; + model.check_secondary_options(&secondary_key, |options| options.unique)?; let table = self.get_secondary_table(&model, &secondary_key)?; let value = table.get(key.database_inner_key_value())?; let primary_key = if let Some(value) = value { - value.value().to_owned() + value.value() } else { return Ok(None); }; diff --git a/src/transaction/internal/r_transaction.rs b/src/transaction/internal/r_transaction.rs index ea3dfc9..cc8a9f0 100644 --- a/src/transaction/internal/r_transaction.rs +++ b/src/transaction/internal/r_transaction.rs @@ -13,8 +13,7 @@ pub struct InternalRTransaction<'db> { impl<'db, 'txn> PrivateReadableTransaction<'db, 'txn> for InternalRTransaction<'db> where - Self: 'txn, - Self: 'db, + Self: 'txn + 'db, { type RedbPrimaryTable = redb::ReadOnlyTable<'txn, DatabaseInnerKeyValue, &'static [u8]>; type RedbSecondaryTable = @@ -22,8 +21,8 @@ where type RedbTransaction<'db_bis> = redb::ReadTransaction<'db> where Self: 'db_bis; - fn table_definitions(&self) -> &HashMap { - &self.table_definitions + fn table_definitions(&self) -> &HashMap> { + self.table_definitions } fn get_primary_table(&'txn self, model: &DatabaseModel) -> Result { @@ -50,7 +49,7 @@ where })?; let secondary_table_definition = main_table_definition .secondary_tables - .get(&secondary_key) + .get(secondary_key) .ok_or_else(|| Error::TableDefinitionNotFound { table: secondary_key.unique_table_name.to_string(), })?; diff --git a/src/transaction/internal/rw_transaction.rs b/src/transaction/internal/rw_transaction.rs index a65b958..7c42a40 100644 --- a/src/transaction/internal/rw_transaction.rs +++ b/src/transaction/internal/rw_transaction.rs @@ -18,16 +18,15 @@ pub struct InternalRwTransaction<'db> { impl<'db, 'txn> PrivateReadableTransaction<'db, 'txn> for InternalRwTransaction<'db> where - Self: 'txn, - Self: 'db, + Self: 'txn + 'db, { type RedbPrimaryTable = redb::Table<'db, 'txn, DatabaseInnerKeyValue, &'static [u8]>; type RedbSecondaryTable = redb::Table<'db, 'txn, DatabaseInnerKeyValue, DatabaseInnerKeyValue>; type RedbTransaction<'db_bis> = redb::WriteTransaction<'db> where Self: 'db_bis; - fn table_definitions(&self) -> &HashMap { - &self.primary_table_definitions + fn table_definitions(&self) -> &HashMap> { + self.primary_table_definitions } fn get_primary_table(&'txn self, model: &DatabaseModel) -> Result { @@ -54,7 +53,7 @@ where })?; let secondary_table_definition = main_table_definition .secondary_tables - .get(&secondary_key) + .get(secondary_key) .ok_or_else(|| Error::TableDefinitionNotFound { table: secondary_key.unique_table_name.to_string(), })?; @@ -84,7 +83,7 @@ impl<'db> InternalRwTransaction<'db> { .is_some(); } - for (secondary_key_def, _value) in &item.secondary_keys { + for secondary_key_def in item.secondary_keys.keys() { let mut secondary_table = self.get_secondary_table(&model, secondary_key_def)?; let result = match item.secondary_key_value(secondary_key_def)? { DatabaseKeyValue::Default(value) => { @@ -101,14 +100,13 @@ impl<'db> InternalRwTransaction<'db> { if result.is_some() && !already_exists { return Err(Error::DuplicateKey { key_name: secondary_key_def.unique_table_name.to_string(), - } - .into()); + }); } } Ok(( WatcherRequest::new( - model.primary_key.unique_table_name.clone(), + model.primary_key.unique_table_name, item.primary_key, item.secondary_keys, ), @@ -121,21 +119,21 @@ impl<'db> InternalRwTransaction<'db> { model: DatabaseModel, item: DatabaseInput, ) -> Result<(WatcherRequest, DatabaseOutputValue)> { - let keys = &item.secondary_keys; + let secondary_keys = &item.secondary_keys; { let mut table = self.get_primary_table(&model)?; - table.remove(&item.primary_key)?; + _ = table.remove(&item.primary_key)?; } - for (secondary_key_def, _value) in keys { + for secondary_key_def in secondary_keys.keys() { let mut secondary_table = self.get_secondary_table(&model, secondary_key_def)?; match &item.secondary_key_value(secondary_key_def)? { DatabaseKeyValue::Default(value) => { - secondary_table.remove(value)?; + _ = secondary_table.remove(value)?; } DatabaseKeyValue::Optional(value) => { if let Some(value) = value { - secondary_table.remove(value)?; + _ = secondary_table.remove(value)?; } } } @@ -143,7 +141,7 @@ impl<'db> InternalRwTransaction<'db> { Ok(( WatcherRequest::new( - model.primary_key.unique_table_name.clone(), + model.primary_key.unique_table_name, item.primary_key, item.secondary_keys, ), @@ -162,7 +160,7 @@ impl<'db> InternalRwTransaction<'db> { Ok((watcher_request, old_binary_value, new_binary_value)) } - pub(crate) fn concrete_primary_drain<'a>( + pub(crate) fn concrete_primary_drain( &self, model: DatabaseModel, ) -> Result> { @@ -176,7 +174,7 @@ impl<'db> InternalRwTransaction<'db> { let (primary_key, value) = result?; // TODO: we should delay to an drain scan let binary_value = DatabaseOutputValue(value.value().to_vec()); - key_items.insert(primary_key.value().to_owned()); + _ = key_items.insert(primary_key.value().to_owned()); items.push(binary_value); } @@ -187,8 +185,7 @@ impl<'db> InternalRwTransaction<'db> { table: model.primary_key.unique_table_name.to_string(), })? .secondary_tables - .iter() - .map(|(key, _)| key) + .keys() .collect(); // Drain secondary tables @@ -213,7 +210,7 @@ impl<'db> InternalRwTransaction<'db> { // Delete secondary keys for secondary_key in secondary_keys_to_delete { - secondary_table.remove(secondary_key)?; + _ = secondary_table.remove(secondary_key)?; } } @@ -230,10 +227,7 @@ impl<'db> InternalRwTransaction<'db> { .native_model_legacy { return Err(Error::MigrateLegacyModel( - T::native_db_model() - .primary_key - .unique_table_name - .to_string(), + T::native_db_model().primary_key.unique_table_name, )); } @@ -241,18 +235,17 @@ impl<'db> InternalRwTransaction<'db> { let mut old_table_definition = None; for new_primary_table_definition in self.primary_table_definitions.values() { // check if table exists, if the table does not exist continue - if self + if !self .redb_transaction .list_tables()? - .find(|table| table.name() == new_primary_table_definition.redb.name()) - .is_none() + .any(|table| table.name() == new_primary_table_definition.redb.name()) { continue; } let table = self .redb_transaction - .open_table(new_primary_table_definition.redb.clone())?; + .open_table(new_primary_table_definition.redb)?; let len = table.len()?; if len > 0 && old_table_definition.is_some() { panic!( @@ -284,7 +277,7 @@ impl<'db> InternalRwTransaction<'db> { for old_data in self.concrete_primary_drain(old_table_definition.model.clone())? { let (decoded_item, _) = native_model::decode::(old_data.0).unwrap(); let decoded_item = decoded_item.to_item(); - self.concrete_insert(T::native_db_model(), decoded_item)?; + _ = self.concrete_insert(T::native_db_model(), decoded_item)?; } Ok(()) diff --git a/src/transaction/query/drain.rs b/src/transaction/query/drain.rs index ef3b8f6..578d66a 100644 --- a/src/transaction/query/drain.rs +++ b/src/transaction/query/drain.rs @@ -13,10 +13,7 @@ impl<'db, 'txn> RwDrain<'db, 'txn> { } /// **TODO: needs to be implemented** - pub fn secondary( - &self, - _key_def: impl KeyDefinition, - ) -> () { - todo!() + pub fn secondary(&self, _key_def: impl KeyDefinition) { + unimplemented!() } } diff --git a/src/transaction/query/scan/primary_scan.rs b/src/transaction/query/scan/primary_scan.rs index 91a7054..889e74b 100644 --- a/src/transaction/query/scan/primary_scan.rs +++ b/src/transaction/query/scan/primary_scan.rs @@ -16,10 +16,10 @@ impl PrimaryScan where PrimaryTable: redb::ReadableTable, { - pub(crate) fn new(table: PrimaryTable) -> Self { + pub(crate) const fn new(table: PrimaryTable) -> Self { Self { primary_table: table, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -52,14 +52,14 @@ where /// Ok(()) /// } /// ``` - pub fn all(&self) -> PrimaryScanIterator { + pub fn all(&self) -> PrimaryScanIterator<'_, T> { let range = self .primary_table .range::(..) .unwrap(); PrimaryScanIterator { range, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -92,7 +92,10 @@ where /// Ok(()) /// } /// ``` - pub fn range>(&self, range: R) -> PrimaryScanIterator { + pub fn range>( + &self, + range: R, + ) -> PrimaryScanIterator<'_, T> { let database_inner_key_value_range = DatabaseInnerKeyValueRange::new(range); let range = self .primary_table @@ -100,7 +103,7 @@ where .unwrap(); PrimaryScanIterator { range, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -145,7 +148,7 @@ where PrimaryScanIteratorStartWith { start_with, range, - _marker: PhantomData::default(), + _marker: PhantomData, } } } diff --git a/src/transaction/query/scan/secondary_scan.rs b/src/transaction/query/scan/secondary_scan.rs index c052563..f4aa34a 100644 --- a/src/transaction/query/scan/secondary_scan.rs +++ b/src/transaction/query/scan/secondary_scan.rs @@ -20,11 +20,11 @@ where PrimaryTable: redb::ReadableTable, SecondaryTable: redb::ReadableTable, { - pub(crate) fn new(primary_table: PrimaryTable, secondary_table: SecondaryTable) -> Self { + pub(crate) const fn new(primary_table: PrimaryTable, secondary_table: SecondaryTable) -> Self { Self { primary_table, secondary_table, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -64,7 +64,7 @@ where /// Ok(()) /// } /// ``` - pub fn all(&self) -> SecondaryScanIterator { + pub fn all(&self) -> SecondaryScanIterator<'_, PrimaryTable, T> { let range = self .secondary_table .range::(..) @@ -72,7 +72,7 @@ where SecondaryScanIterator { primary_table: &self.primary_table, range, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -112,7 +112,7 @@ where pub fn range>( &self, range: R, - ) -> SecondaryScanIterator { + ) -> SecondaryScanIterator<'_, PrimaryTable, T> { let database_inner_key_value_range = DatabaseInnerKeyValueRange::new(range); let range = self .secondary_table @@ -121,7 +121,7 @@ where SecondaryScanIterator { primary_table: &self.primary_table, range, - _marker: PhantomData::default(), + _marker: PhantomData, } } @@ -171,7 +171,7 @@ where primary_table: &self.primary_table, start_with, range, - _marker: PhantomData::default(), + _marker: PhantomData, } } } @@ -193,13 +193,10 @@ where fn next(&mut self) -> Option { match self.range.next() { - Some(Ok((_, key))) => { - if let Ok(value) = self.primary_table.get(key.value()) { - unwrap_item(value) - } else { - None - } - } + Some(Ok((_, key))) => self + .primary_table + .get(key.value()) + .map_or_else(|_| None, |value| unwrap_item(value)), _ => None, } } diff --git a/src/transaction/r_transaction.rs b/src/transaction/r_transaction.rs index 68cdefa..d54f48a 100644 --- a/src/transaction/r_transaction.rs +++ b/src/transaction/r_transaction.rs @@ -9,21 +9,21 @@ pub struct RTransaction<'db> { impl<'db> RTransaction<'db> { /// Get a value from the database. - pub fn get<'txn>(&'txn self) -> RGet<'db, 'txn> { + pub const fn get<'txn>(&'txn self) -> RGet<'db, 'txn> { RGet { internal: &self.internal, } } /// Get values from the database. - pub fn scan<'txn>(&'txn self) -> RScan<'db, 'txn> { + pub const fn scan<'txn>(&'txn self) -> RScan<'db, 'txn> { RScan { internal: &self.internal, } } /// Get the number of values in the database. - pub fn len<'txn>(&'txn self) -> RLen<'db, 'txn> { + pub const fn len<'txn>(&'txn self) -> RLen<'db, 'txn> { RLen { internal: &self.internal, } diff --git a/src/transaction/rw_transaction.rs b/src/transaction/rw_transaction.rs index 3f749cd..c5b5040 100644 --- a/src/transaction/rw_transaction.rs +++ b/src/transaction/rw_transaction.rs @@ -20,7 +20,7 @@ impl<'db> RwTransaction<'db> { /// Get a value from the database. /// /// Same as [`RTransaction::get()`](struct.RTransaction.html#method.get). - pub fn get<'txn>(&'txn self) -> RwGet<'db, 'txn> { + pub const fn get<'txn>(&'txn self) -> RwGet<'db, 'txn> { RwGet { internal: &self.internal, } @@ -29,7 +29,7 @@ impl<'db> RwTransaction<'db> { /// Get values from the database. /// /// Same as [`RTransaction::scan()`](struct.RTransaction.html#method.scan). - pub fn scan<'txn>(&'txn self) -> RwScan<'db, 'txn> { + pub const fn scan<'txn>(&'txn self) -> RwScan<'db, 'txn> { RwScan { internal: &self.internal, } @@ -38,7 +38,7 @@ impl<'db> RwTransaction<'db> { /// Get the number of values in the database. /// /// Same as [`RTransaction::len()`](struct.RTransaction.html#method.len). - pub fn len<'txn>(&'txn self) -> RwLen<'db, 'txn> { + pub const fn len<'txn>(&'txn self) -> RwLen<'db, 'txn> { RwLen { internal: &self.internal, } @@ -47,14 +47,14 @@ impl<'db> RwTransaction<'db> { /// Get all values from the database. /// /// Same as [`RTransaction::drain()`](struct.RTransaction.html#method.drain). - pub fn drain<'txn>(&'txn self) -> RwDrain<'db, 'txn> { + pub const fn drain<'txn>(&'txn self) -> RwDrain<'db, 'txn> { RwDrain { internal: &self.internal, } } } -impl<'db, 'txn> RwTransaction<'db> { +impl<'db> RwTransaction<'db> { /// Commit the transaction. /// All changes will be applied to the database. If the commit fails, the transaction will be aborted. The /// database will be unchanged. @@ -79,12 +79,12 @@ impl<'db, 'txn> RwTransaction<'db> { self.internal.commit()?; // Send batch to watchers after commit succeeds let batch = self.batch.into_inner(); - watch::push_batch(Arc::clone(&self.watcher), batch)?; + watch::push_batch(Arc::clone(self.watcher), batch)?; Ok(()) } } -impl<'db, 'txn> RwTransaction<'db> { +impl<'db> RwTransaction<'db> { /// Insert a value into the database. /// /// # Example @@ -279,9 +279,11 @@ impl<'db, 'txn> RwTransaction<'db> { let find_all_old: Vec = self.scan().primary()?.all().collect(); for old in find_all_old { let new: NewType = old.clone().into(); - self.internal + _ = self + .internal .concrete_insert(NewType::native_db_model(), new.to_item())?; - self.internal + _ = self + .internal .concrete_remove(OldType::native_db_model(), old.to_item())?; } Ok(()) diff --git a/src/watch/batch.rs b/src/watch/batch.rs index d04f3ea..83fd6b5 100644 --- a/src/watch/batch.rs +++ b/src/watch/batch.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; pub struct Batch(Vec<(WatcherRequest, Event)>); impl Batch { - pub(crate) fn new() -> Self { + pub(crate) const fn new() -> Self { Self(Vec::new()) } @@ -14,7 +14,7 @@ impl Batch { } } -impl<'a> Iterator for Batch { +impl Iterator for Batch { type Item = (WatcherRequest, Event); fn next(&mut self) -> Option { diff --git a/src/watch/event.rs b/src/watch/event.rs index abe0453..667c409 100644 --- a/src/watch/event.rs +++ b/src/watch/event.rs @@ -9,11 +9,11 @@ pub enum Event { } impl Event { - pub(crate) fn new_insert(value: DatabaseOutputValue) -> Self { + pub(crate) const fn new_insert(value: DatabaseOutputValue) -> Self { Self::Insert(Insert(value)) } - pub(crate) fn new_update( + pub(crate) const fn new_update( old_value: DatabaseOutputValue, new_value: DatabaseOutputValue, ) -> Self { @@ -23,7 +23,7 @@ impl Event { }) } - pub(crate) fn new_delete(value: DatabaseOutputValue) -> Self { + pub(crate) const fn new_delete(value: DatabaseOutputValue) -> Self { Self::Delete(Delete(value)) } } @@ -31,14 +31,14 @@ impl Event { impl Debug for Event { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Event::Insert(_) => write!(f, "Insert"), - Event::Update(_) => write!(f, "Update"), - Event::Delete(_) => write!(f, "Delete"), + Self::Insert(_) => write!(f, "Insert"), + Self::Update(_) => write!(f, "Update"), + Self::Delete(_) => write!(f, "Delete"), } } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Insert(pub(crate) DatabaseOutputValue); impl Insert { @@ -47,7 +47,7 @@ impl Insert { } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Update { pub(crate) old: DatabaseOutputValue, pub(crate) new: DatabaseOutputValue, @@ -62,7 +62,7 @@ impl Update { } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Delete(pub(crate) DatabaseOutputValue); impl Delete { diff --git a/src/watch/filter.rs b/src/watch/filter.rs index 4571343..2aec954 100644 --- a/src/watch/filter.rs +++ b/src/watch/filter.rs @@ -3,13 +3,13 @@ use crate::db_type::{ }; #[derive(Eq, PartialEq, Clone)] -pub(crate) struct TableFilter { +pub struct TableFilter { pub(crate) table_name: String, pub(crate) key_filter: KeyFilter, } #[derive(Eq, PartialEq, Clone)] -pub(crate) enum KeyFilter { +pub enum KeyFilter { Primary(Option), PrimaryStartWith(DatabaseInnerKeyValue), Secondary( @@ -23,20 +23,23 @@ pub(crate) enum KeyFilter { } impl TableFilter { - pub(crate) fn new_primary(table_name: String, key: Option) -> Self { + pub(crate) const fn new_primary( + table_name: String, + key: Option, + ) -> Self { Self { table_name, - key_filter: KeyFilter::Primary(key.map(|k| k.to_owned())), + key_filter: KeyFilter::Primary(key), } } - pub(crate) fn new_primary_start_with( + pub(crate) const fn new_primary_start_with( table_name: String, key_prefix: DatabaseInnerKeyValue, ) -> Self { Self { table_name, - key_filter: KeyFilter::PrimaryStartWith(key_prefix.to_owned()), + key_filter: KeyFilter::PrimaryStartWith(key_prefix), } } @@ -47,7 +50,7 @@ impl TableFilter { ) -> Self { Self { table_name, - key_filter: KeyFilter::Secondary(key_def.database_key(), key.map(|k| k.to_owned())), + key_filter: KeyFilter::Secondary(key_def.database_key(), key), } } @@ -58,7 +61,7 @@ impl TableFilter { ) -> Self { Self { table_name, - key_filter: KeyFilter::SecondaryStartWith(key.database_key(), key_prefix.to_owned()), + key_filter: KeyFilter::SecondaryStartWith(key.database_key(), key_prefix), } } } diff --git a/src/watch/mod.rs b/src/watch/mod.rs index 7a6e7ec..07bc76a 100644 --- a/src/watch/mod.rs +++ b/src/watch/mod.rs @@ -44,15 +44,16 @@ pub(crate) fn push_batch( senders: Arc>, batch: Batch, ) -> Result<(), WatchEventError> { - let watchers = senders.try_read().map_err(|err| match err { - TryLockError::Poisoned(_) => WatchEventError::TryLockErrorPoisoned, - TryLockError::WouldBlock => WatchEventError::TryLockErrorWouldBlock, - })?; - for (watcher_request, event) in batch { - for sender in watchers.find_senders(&watcher_request) { - let sender = sender.lock().unwrap(); - sender.send(event.clone())?; + let find_senders = senders + .try_read() + .map_err(|err| match err { + TryLockError::Poisoned(_) => WatchEventError::TryLockErrorPoisoned, + TryLockError::WouldBlock => WatchEventError::TryLockErrorWouldBlock, + })? + .find_senders(&watcher_request); + for sender in find_senders { + sender.lock().unwrap().send(event.clone())?; } } diff --git a/src/watch/query/internal.rs b/src/watch/query/internal.rs index 54ff596..15e1ce4 100644 --- a/src/watch/query/internal.rs +++ b/src/watch/query/internal.rs @@ -6,7 +6,7 @@ use crate::watch::{MpscReceiver, TableFilter}; use std::sync::atomic::AtomicU64; use std::sync::{Arc, Mutex, RwLock}; -pub(crate) struct InternalWatch<'db> { +pub struct InternalWatch<'db> { pub(crate) watchers: &'db Arc>, pub(crate) watchers_counter_id: &'db AtomicU64, } @@ -14,7 +14,7 @@ pub(crate) struct InternalWatch<'db> { impl InternalWatch<'_> { fn watch_generic( &self, - table_filter: watch::TableFilter, + table_filter: TableFilter, ) -> Result<(MpscReceiver, u64)> { #[cfg(not(feature = "tokio"))] let (event_sender, event_receiver) = std::sync::mpsc::channel(); @@ -33,7 +33,7 @@ impl InternalWatch<'_> { .watchers_counter_id .fetch_add(1, std::sync::atomic::Ordering::SeqCst); if value == u64::MAX { - Err(Error::MaxWatcherReached.into()) + Err(Error::MaxWatcherReached) } else { Ok(value) } @@ -45,14 +45,13 @@ impl InternalWatch<'_> { ) -> Result<(MpscReceiver, u64)> { let table_name = T::native_db_model().primary_key; let key = key.database_inner_key_value(); - let table_filter = - TableFilter::new_primary(table_name.unique_table_name.clone(), Some(key)); + let table_filter = TableFilter::new_primary(table_name.unique_table_name, Some(key)); self.watch_generic(table_filter) } pub(crate) fn watch_primary_all(&self) -> Result<(MpscReceiver, u64)> { let table_name = T::native_db_model().primary_key; - let table_filter = TableFilter::new_primary(table_name.unique_table_name.clone(), None); + let table_filter = TableFilter::new_primary(table_name.unique_table_name, None); self.watch_generic(table_filter) } @@ -63,7 +62,7 @@ impl InternalWatch<'_> { let table_name = T::native_db_model().primary_key; let start_with = start_with.database_inner_key_value(); let table_filter = - TableFilter::new_primary_start_with(table_name.unique_table_name.clone(), start_with); + TableFilter::new_primary_start_with(table_name.unique_table_name, start_with); self.watch_generic(table_filter) } @@ -75,7 +74,7 @@ impl InternalWatch<'_> { let table_name = T::native_db_model().primary_key; let key = key.database_inner_key_value(); let table_filter = - TableFilter::new_secondary(table_name.unique_table_name.clone(), key_def, Some(key)); + TableFilter::new_secondary(table_name.unique_table_name, key_def, Some(key)); self.watch_generic(table_filter) } @@ -84,8 +83,7 @@ impl InternalWatch<'_> { key_def: &impl KeyDefinition, ) -> Result<(MpscReceiver, u64)> { let table_name = T::native_db_model().primary_key; - let table_filter = - TableFilter::new_secondary(table_name.unique_table_name.clone(), key_def, None); + let table_filter = TableFilter::new_secondary(table_name.unique_table_name, key_def, None); self.watch_generic(table_filter) } @@ -97,7 +95,7 @@ impl InternalWatch<'_> { let table_name = T::native_db_model().primary_key; let start_with = start_with.database_inner_key_value(); let table_filter = TableFilter::new_secondary_start_with( - table_name.unique_table_name.clone(), + table_name.unique_table_name, key_def, start_with, ); diff --git a/src/watch/query/mod.rs b/src/watch/query/mod.rs index 30fb67a..f461867 100644 --- a/src/watch/query/mod.rs +++ b/src/watch/query/mod.rs @@ -13,13 +13,13 @@ pub struct Watch<'db> { impl<'db> Watch<'db> { /// Watch only one value. - pub fn get<'w>(&'w self) -> WatchGet<'db, 'w> { + pub const fn get<'w>(&'w self) -> WatchGet<'db, 'w> { WatchGet { internal: &self.internal, } } /// Watch multiple values. - pub fn scan<'w>(&'w self) -> WatchScan<'db, 'w> { + pub const fn scan<'w>(&'w self) -> WatchScan<'db, 'w> { WatchScan { internal: &self.internal, } diff --git a/src/watch/query/scan.rs b/src/watch/query/scan.rs index f8052c4..70d4afd 100644 --- a/src/watch/query/scan.rs +++ b/src/watch/query/scan.rs @@ -14,9 +14,9 @@ pub struct WatchScan<'db, 'w> { /// Watch multiple values. impl WatchScan<'_, '_> { /// Watch all values. - pub fn primary(&self) -> WatchScanPrimary { + pub const fn primary(&self) -> WatchScanPrimary<'_, '_> { WatchScanPrimary { - internal: &self.internal, + internal: self.internal, } } @@ -24,10 +24,10 @@ impl WatchScan<'_, '_> { pub fn secondary( &self, key_def: impl KeyDefinition, - ) -> WatchScanSecondary { + ) -> WatchScanSecondary<'_, '_> { WatchScanSecondary { key_def: key_def.database_key(), - internal: &self.internal, + internal: self.internal, } } } @@ -154,7 +154,7 @@ impl WatchScanSecondary<'_, '_> { /// Ok(()) /// } /// ``` - pub fn all<'ws, T: Input>(&'ws self) -> Result<(MpscReceiver, u64)> { + pub fn all(&self) -> Result<(MpscReceiver, u64)> { self.internal.watch_secondary_all::(&self.key_def) } diff --git a/src/watch/request.rs b/src/watch/request.rs index 7ac8483..fa0fa6f 100644 --- a/src/watch/request.rs +++ b/src/watch/request.rs @@ -13,7 +13,7 @@ pub struct WatcherRequest { } impl WatcherRequest { - pub fn new( + pub const fn new( table_name: String, primary_key: DatabaseInnerKeyValue, secondary_keys: HashMap< diff --git a/src/watch/sender.rs b/src/watch/sender.rs index 545199a..2bed180 100644 --- a/src/watch/sender.rs +++ b/src/watch/sender.rs @@ -5,7 +5,7 @@ use crate::watch::{Event, MpscSender}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; -pub(crate) struct Watchers(HashMap>>)>); +pub struct Watchers(HashMap>>)>); impl Watchers { pub(crate) fn new() -> Self { @@ -18,11 +18,11 @@ impl Watchers { table_filter: &TableFilter, event_sender: Arc>>, ) { - self.0.insert(id, (table_filter.clone(), event_sender)); + _ = self.0.insert(id, (table_filter.clone(), event_sender)); } pub(crate) fn remove_sender(&mut self, id: u64) { - self.0.remove(&id); + _ = self.0.remove(&id); } pub(crate) fn find_senders( @@ -30,7 +30,7 @@ impl Watchers { request: &WatcherRequest, ) -> Vec>>> { let mut event_senders = Vec::new(); - for (_, (filter, event_sender)) in &self.0 { + for (filter, event_sender) in self.0.values() { if filter.table_name == request.table_name { match &filter.key_filter { KeyFilter::Primary(value) => { @@ -83,18 +83,18 @@ impl Watchers { { match request_secondary_key { DatabaseKeyValue::Default(value) => { - if key_def == request_secondary_key_def { - if value.as_slice().starts_with(key_prefix.as_slice()) { - event_senders.push(Arc::clone(event_sender)); - } + if key_def == request_secondary_key_def + && value.as_slice().starts_with(key_prefix.as_slice()) + { + event_senders.push(Arc::clone(event_sender)); } } DatabaseKeyValue::Optional(value) => { if let Some(value) = value { - if key_def == request_secondary_key_def { - if value.as_slice().starts_with(key_prefix.as_slice()) { - event_senders.push(Arc::clone(event_sender)); - } + if key_def == request_secondary_key_def + && value.as_slice().starts_with(key_prefix.as_slice()) + { + event_senders.push(Arc::clone(event_sender)); } } } diff --git a/tests/custom_type/chrono.rs b/tests/custom_type/chrono.rs index 53a70e3..6eb6677 100644 --- a/tests/custom_type/chrono.rs +++ b/tests/custom_type/chrono.rs @@ -32,7 +32,7 @@ fn insert_get() { let r = db.r_transaction().unwrap(); let result_item = r .get() - .secondary(ItemKey::timestamp, &item.timestamp) + .secondary(ItemKey::timestamp, item.timestamp) .unwrap() .unwrap(); assert_eq!(item, result_item); diff --git a/tests/custom_type/uuid.rs b/tests/custom_type/uuid.rs index 4eb6262..cb72784 100644 --- a/tests/custom_type/uuid.rs +++ b/tests/custom_type/uuid.rs @@ -28,6 +28,6 @@ fn insert_get() { rw.commit().unwrap(); let r = db.r_transaction().unwrap(); - let result_item = r.get().primary(&item.uuid).unwrap().unwrap(); + let result_item = r.get().primary(item.uuid).unwrap().unwrap(); assert_eq!(item, result_item); } diff --git a/tests/macro_def/secondary_key.rs b/tests/macro_def/secondary_key.rs index 91037f9..14d79a5 100644 --- a/tests/macro_def/secondary_key.rs +++ b/tests/macro_def/secondary_key.rs @@ -107,11 +107,9 @@ impl ItemSecondaryOptional { format!("{}", self.id) } pub fn compute_secondary_key(&self) -> Option { - if let Some(name) = &self.name { - Some(format!("{}-{}", name, self.id)) - } else { - None - } + self.name + .as_ref() + .map(|name| format!("{}-{}", name, self.id)) } } diff --git a/tests/native_model.rs b/tests/native_model.rs index 8f7fb94..1263af5 100644 --- a/tests/native_model.rs +++ b/tests/native_model.rs @@ -1,4 +1,3 @@ -use bincode; use bincode::{config, Decode, Encode}; use native_db::*; use native_db_macro::native_db; diff --git a/tests/scan.rs b/tests/scan.rs index 0a02f36..fde6eb5 100644 --- a/tests/scan.rs +++ b/tests/scan.rs @@ -28,10 +28,10 @@ impl Item { self.id } pub fn secondary_key_1(&self) -> String { - format!("{}", self.id).into() + format!("{}", self.id) } pub fn secondary_key_2(&self) -> String { - format!("{}", self.name) + self.name.to_string() } } diff --git a/tests/watch_tokio.rs b/tests/watch_tokio.rs index 52eb24f..0007dec 100644 --- a/tests/watch_tokio.rs +++ b/tests/watch_tokio.rs @@ -20,7 +20,7 @@ async fn watch_one_primary_key() { let mut builder = DatabaseBuilder::new(); builder.define::().unwrap(); - let mut db = builder.create(tf.path("test").as_std_path()).unwrap(); + let db = builder.create(tf.path("test").as_std_path()).unwrap(); let a = ItemA { id: 1 }; From f12f9ae317c8b103377e77dc2d3f7d74c0f96238 Mon Sep 17 00:00:00 2001 From: simonsan <14062932+simonsan@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:28:15 +0100 Subject: [PATCH 2/2] ci: add ci Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com> --- .github/workflows/ci.yml | 155 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..47043b3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,155 @@ +name: Continuous Integration + +on: + pull_request: + paths-ignore: + - "**/*.md" + push: + branches: + - main + paths-ignore: + - "**/*.md" + schedule: + - cron: "0 0 * * 0" + merge_group: + types: [checks_requested] + +jobs: + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8 # v1 + with: + toolchain: stable + - run: rustup component add rustfmt + - name: Run Cargo Fmt + run: cargo fmt --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8 # v1 + with: + toolchain: stable + components: clippy + - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2 + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + test: + name: Test + runs-on: ${{ matrix.job.os }} + strategy: + matrix: + rust: [stable] + job: + - os: macos-latest + - os: ubuntu-latest + - os: windows-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name != 'pull_request' + with: + fetch-depth: 0 + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name == 'pull_request' + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8 # v1 + with: + toolchain: ${{ matrix.rust }} + - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2 + - name: Run Cargo Test + run: cargo +${{ matrix.rust }} test -r --all-targets --all-features --workspace + + docs: + name: Build docs + runs-on: ${{ matrix.job.os }} + strategy: + matrix: + rust: [stable] + job: + - os: macos-latest + - os: ubuntu-latest + - os: windows-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name != 'pull_request' + with: + fetch-depth: 0 + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name == 'pull_request' + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8 # v1 + with: + toolchain: ${{ matrix.rust }} + - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2 + - name: Run Cargo Doc + run: cargo +${{ matrix.rust }} doc --no-deps --all-features --workspace --examples + + powerset: + name: Check Powerset of Features + runs-on: ${{ matrix.job.os }} + strategy: + matrix: + rust: [stable, beta, nightly] + job: + - os: macos-latest + - os: ubuntu-latest + - os: windows-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name != 'pull_request' + with: + fetch-depth: 0 + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + if: github.event_name == 'pull_request' + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8 # v1 + with: + toolchain: ${{ matrix.rust }} + - name: install cargo-hack + uses: taiki-e/install-action@2b8d4e021f3c5d9b9d4726c038ac367d3ed730b6 # v2 + with: + tool: cargo-hack + - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2 + - name: Run Cargo Hack + run: cargo +${{ matrix.rust }} hack check --feature-powerset --no-dev-deps + + result: + name: Result (CI) + runs-on: ubuntu-latest + needs: + - fmt + - clippy + - test + - docs + - powerset + steps: + - name: Mark the job as successful + run: exit 0 + if: success() + - name: Mark the job as unsuccessful + run: exit 1 + if: "!success()"