Переглянути джерело

Address clippy nits and add some more documentation.

Kestrel 3 тижнів тому
батько
коміт
ecd4f1b7de

+ 10 - 3
microrm/src/db.rs

@@ -28,6 +28,10 @@ pub struct ConnectionData {
     stmts: RefCell<HashMap<u64, Statement>>,
 }
 
+// sqlite connections can be used in different threads as long as it's not concurrent us, so
+// ConnectionData is Send.
+unsafe impl Send for ConnectionPoolData {}
+
 impl Drop for ConnectionData {
     fn drop(&mut self) {
         self.stmts.borrow_mut().clear();
@@ -222,6 +226,12 @@ struct ConnectionPoolData {
     connections: Vec<ConnectionData>,
 }
 
+// the way the ConnectionData instances are accessed is guarded by the `available` mutex, and
+// sqlite connections are safe to be sent between threads as long as there is no concurrent access.
+//
+// so while ConnectionData is *not* Sync, ConnectionPoolData is.
+unsafe impl Sync for ConnectionPoolData {}
+
 impl ConnectionPoolData {
     fn spawn(&mut self, count: usize) -> Result<(), Error> {
         let mut alock = self.available.lock()?;
@@ -340,9 +350,6 @@ impl ConnectionPool {
     }
 }
 
-unsafe impl Send for ConnectionPool {}
-unsafe impl Sync for ConnectionPool {}
-
 pub(crate) struct Transaction<'l, 'd: 'l> {
     db: &'l mut ConnectionLease<'d>,
     committed: bool,

+ 7 - 6
microrm/src/lib.rs

@@ -46,7 +46,6 @@
 //! let mut lease = cpool.acquire()?;
 //! let schema = KVSchema::default();
 //! schema.install(&mut lease)?;
-//! // let db = KVSchema::open_path(":memory:")?;
 //! schema.kvs.insert(&mut lease, KVEntry {
 //!     key: "example_key".to_string(),
 //!     value: "example_value".to_string()
@@ -119,13 +118,14 @@
 //! #[derive(Entity)]
 //! pub struct Customer {
 //!     pub orders: microrm::RelationDomain<CustomerOrders>,
-//!
+//!     // mark as part of the primary key
 //!     #[key]
 //!     pub email: String,
-//!
+//!     // enforce uniqueness of legal names
 //!     #[unique]
 //!     pub legal_name: String,
 //!
+//!     // elide the secrets from Debug output
 //!     #[elide]
 //!     pub password_salt: String,
 //!     #[elide]
@@ -144,13 +144,15 @@
 //!
 //! #[derive(Entity)]
 //! pub struct Order {
+//!     // use an ordinary type and do transparent JSON de/serialization
 //!     pub order_state: microrm::Serialized<Vec<OrderState>>,
 //!     pub customer: microrm::RelationRange<CustomerOrders>,
 //!     pub shipping_address: String,
 //!
+//!     // we may not have a billing address
 //!     pub billing_address: Option<String>,
 //!
-//!     // we'll assume for now that there's no product multiplicities, i.e. this is not a multiset
+//!     // we'll assume for now that there's no product multiplicities, i.e. `contents` is not a multiset
 //!     pub contents: microrm::RelationMap<Product>,
 //! }
 //!
@@ -165,7 +167,6 @@
 //! let cpool = microrm::ConnectionPool::new(":memory:")?;
 //! let mut lease = cpool.acquire()?;
 //! let schema = ECommerceDB::default();
-//! // let db = ECommerceDB::open_path(":memory:")?;
 //! schema.install(&mut lease);
 //!
 //! // add an example product
@@ -244,7 +245,7 @@ pub use schema::{IDMap, Serialized, Stored};
 #[cfg(feature = "clap")]
 pub mod cli;
 
-/// Module prelude with commonly-used traits that shouldn't have overlap with other crates.
+/// Re-exported traits and macros for easy access.
 pub mod prelude {
     pub use crate::query::{Insertable, Queryable, RelationInterface};
     pub use crate::schema::{relation::Relation, Schema, Serializable};

+ 1 - 1
microrm/src/schema.rs

@@ -309,7 +309,7 @@ pub trait DatabaseItemVisitor {
 
 /// A root structure for the database specification graph.
 pub trait Schema: Default {
-    ///
+    /// Install this schema into a database
     fn install(&self, lease: &mut ConnectionLease) -> DBResult<()>
     where
         Self: Sized,

+ 9 - 11
microrm/src/schema/collect.rs

@@ -182,17 +182,15 @@ impl EntityStateContainer {
         //  2b. this entity has an idmap already
 
         use std::collections::hash_map::Entry;
-        match entry {
-            Entry::Occupied(mut entry) => {
-                if entry.get().has_idmap && is_idmap {
-                    panic!("duplicate IDMap for entity {}", E::entity_name())
-                } else if is_idmap {
-                    entry.get_mut().has_idmap = true;
-                }
-                return;
-            },
-            _ => (),
-        };
+
+        if let Entry::Occupied(mut entry) = entry {
+            if entry.get().has_idmap && is_idmap {
+                panic!("duplicate IDMap for entity {}", E::entity_name())
+            } else if is_idmap {
+                entry.get_mut().has_idmap = true;
+            }
+            return;
+        }
 
         let entry = entry.or_insert_with(EntityState::build::<E>);
         entry.has_idmap = is_idmap;

+ 3 - 3
microrm/src/schema/relation.rs

@@ -30,12 +30,12 @@ pub trait Relation: 'static {
     const NAME: &'static str;
 }
 
-/// Enumeration used to represent which side of a relation an [`RelationInterface`] trait implementation is representing.
+/// Enumeration used to represent which side of a relation a [`Relation`] trait implementation is representing.
 #[derive(Debug)]
 pub enum LocalSide {
-    /// The side of the relation that the [`RelationInterface`] represents is the `Domain` side.
+    /// The side of the relation that the [`Relation`] represents is the `Domain` side.
     Domain,
-    /// The side of the relation that the [`RelationInterface`] represents is the `Range` side.
+    /// The side of the relation that the [`Relation`] represents is the `Range` side.
     Range,
 }