Procházet zdrojové kódy

Finished documenting every public type.

Kestrel před 7 měsíci
rodič
revize
23bffd4f64

+ 8 - 1
microrm/src/cli.rs

@@ -28,6 +28,7 @@ pub use clap_interface::{ClapInterface, InterfaceCustomization, ValueRole};
 /// [`Error`] but can be implemented for other error types if extra information needs to be passed
 /// back.
 pub trait CLIError: From<Error> {
+    /// Complain about an entity by a given list of members not existing.
     fn no_such_entity(ename: &'static str, query: String) -> Self;
 }
 
@@ -40,16 +41,22 @@ impl CLIError for Error {
 /// Extension trait on top of [`Entity`] that provides necessary functionality to interact with
 /// instances from the command-line, such as the data required to create an object.
 pub trait CLIObject: Sized + Entity + std::fmt::Debug {
+    /// What kind of error type should be generated when issues are encountered.
     type Error: CLIError;
+    /// Extra data to pass into methods.
     type CommandData;
 
+    /// Required data to create an instance of `Self`.
     type CreateParameters: clap::Parser + std::fmt::Debug;
+    /// Create an instance of `Self` from a `CommandData` instance and a `CreateParameters` instance.
     fn create_from_params(
         _: &Self::CommandData,
         _: &Self::CreateParameters,
     ) -> Result<Self, Self::Error>;
 
+    /// Subcommand type representing all custom operations on this CLIObject implementation.
     type ExtraCommands: clap::Subcommand + std::fmt::Debug;
+    /// Function that handles a constructed `Self::ExtraCommands` instance from clap.
     fn run_extra_command(
         _data: &Self::CommandData,
         _extra: &Self::ExtraCommands,
@@ -60,7 +67,7 @@ pub trait CLIObject: Sized + Entity + std::fmt::Debug {
     }
 
     /// A short string used for display purposes to describe this object. Can be the output of
-    /// Debug.
+    /// Debug or empty.
     fn shortname(&self) -> String;
 }
 

+ 8 - 0
microrm/src/cli/clap_interface.rs

@@ -295,14 +295,22 @@ impl<'l, Error: CLIError, OE: Entity> DatumDiscriminatorRef for Attacher<'l, Err
     }
 }
 
+/// Enumeration that describes the role of a value in an [`InterfaceCustomization`] instance.
 #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
 pub enum ValueRole {
+    /// This value is for the 'base' object, i.e. the first object type specified in a command.
     BaseTarget,
+    /// This value is for the 'attachment' object, i.e. the second object type specified in a command.
     AttachmentTarget,
 }
 
+/// Allows customization of the autogenerated commands by programmatically providing values so they
+/// don't have to be specified on the command-line.
 pub trait InterfaceCustomization {
+    /// Returns true iff this customization will provide a value for this field.
     fn has_value_for(entity: &'static str, field: &'static str, role: ValueRole) -> bool;
+    /// Returns a string representation of the value for this field, equivalent to a value entered
+    /// on the command-line.
     fn value_for(&self, entity: &'static str, field: &'static str, role: ValueRole) -> String;
 }
 

+ 2 - 0
microrm/src/db.rs

@@ -380,6 +380,7 @@ impl<'a> StatementContext<'a> {
 
     // this needs to be replaced with a "single" version that keeps the StatementContext alive, or
     // StatementRow needs an optional StatementContext to keep alive
+    #[doc(hidden)]
     pub fn run(self) -> DBResult<Option<StatementRow<'a>>> {
         if self.step()? {
             Ok(Some(StatementRow {
@@ -391,6 +392,7 @@ impl<'a> StatementContext<'a> {
         }
     }
 
+    #[doc(hidden)]
     pub fn iter(self) -> impl Iterator<Item = DBResult<StatementRow<'a>>> {
         struct I<'a>(StatementContext<'a>);
 

+ 23 - 0
microrm/src/query.rs

@@ -364,16 +364,25 @@ fn do_connect<Remote: Entity>(
     )
 }
 
+/// Assocation (relation) map generic interface trait.
 pub trait AssocInterface: 'static {
+    /// The type of the entity on the non-local end of the relation.
     type RemoteEntity: Entity;
+
+    #[doc(hidden)]
     fn get_data(&self) -> DBResult<&AssocData>;
+    #[doc(hidden)]
     fn get_distinguishing_name(&self) -> DBResult<&'static str>;
+
+    /// Which side is the "local" side of the relation.
     const SIDE: LocalSide;
 
+    /// Query this entity type without the association filter.
     fn query_all(&self) -> impl Queryable<EntityOutput = Self::RemoteEntity> {
         components::TableComponent::<Self::RemoteEntity>::new(self.get_data().unwrap().conn.clone())
     }
 
+    /// Attempt to connect the contextual instance to a remote instance.
     fn connect_to(&self, remote_id: <Self::RemoteEntity as Entity>::ID) -> DBResult<()>
     where
         Self: Sized,
@@ -388,6 +397,7 @@ pub trait AssocInterface: 'static {
         txn.commit()
     }
 
+    /// Attempt to disconnect the contextual instance from a remote instance.
     fn disconnect_from(&self, remote_id: <Self::RemoteEntity as Entity>::ID) -> DBResult<()>
     where
         Self: Sized,
@@ -424,8 +434,12 @@ pub trait AssocInterface: 'static {
 // New query interface
 // ----------------------------------------------------------------------
 
+/// Represents a context in which we can insert an entity type `E`.
 pub trait Insertable<E: Entity> {
+    /// Insert an entity instance and return its new ID.
     fn insert(&self, value: E) -> DBResult<E::ID>;
+    /// Insert an entity instance and return a [`Stored`] instance that can be used to synchronize
+    /// its values back into the database later.
     fn insert_and_return(&self, value: E) -> DBResult<Stored<E>>;
 }
 
@@ -509,13 +523,22 @@ impl<T: Entity> OutputContainer<T> for Vec<Stored<T>> {
     }
 }
 
+/// Represents a searchable context of a given entity.
 pub trait Queryable: Clone {
+    /// The entity that results from a search in this context.
     type EntityOutput: Entity;
+    /// How results will be provided. This is either a `Vec` or an `Option`.
     type OutputContainer: OutputContainer<Self::EntityOutput>;
+    /// A `'static`-version of `Self`, used for `TypeId`-based caching.
     type StaticVersion: Queryable + 'static;
 
+    /// Construct a concrete SQL query from this abstract type representation.
+    #[doc(hidden)]
     fn build(&self) -> Query;
+    /// Bind into any required placeholders to 'fill' an instance created by [`build`].
+    #[doc(hidden)]
     fn bind(&self, stmt: &mut StatementContext, index: &mut i32);
+    #[doc(hidden)]
     fn conn(&self) -> &Connection;
 
     // ----------------------------------------------------------------------

+ 30 - 4
microrm/src/schema/datum.rs

@@ -15,8 +15,11 @@ mod datum_list;
 
 /// Represents a data field in an Entity.
 pub trait Datum: Clone + std::fmt::Debug {
+    /// The type used in a SQL database to represent this datum.
     fn sql_type() -> &'static str;
 
+    /// Generate a `std::fmt::Debug`-compatible view of the current datum; used to produce more
+    /// human-friendly outputs for some more complicated types with state stored in the database.
     fn debug_field(&self, field: &'static str, fmt: &mut std::fmt::DebugStruct)
     where
         Self: Sized,
@@ -24,16 +27,23 @@ pub trait Datum: Clone + std::fmt::Debug {
         fmt.field(field, self);
     }
 
+    /// Bind this datum to a [`StatementContext`] at a given index.
     fn bind_to(&self, _stmt: &mut StatementContext, index: i32);
+    /// Construct an instance of this datum from a table row.
     fn build_from(_adata: AssocData, _stmt: &mut StatementRow, _index: &mut i32) -> DBResult<Self>
     where
         Self: Sized,
     {
         unreachable!()
     }
+
+    /// Update any [`AssocData`] instances.
+    #[doc(hidden)]
     fn update_adata(&mut self, _adata: AssocData) {}
 
+    /// Accept an entity visitor to iterate across any entities this Datum type references.
     fn accept_entity_visitor(_: &mut impl EntityVisitor) {}
+    /// Accept a datum discriminator without any instance reference to allow for more fine-grained per-type processing.
     fn accept_discriminator(d: &mut impl DatumDiscriminator)
     where
         Self: Sized,
@@ -41,6 +51,7 @@ pub trait Datum: Clone + std::fmt::Debug {
         d.visit_bare_field::<Self>();
     }
 
+    /// Accept a datum discriminator with an instance reference to allow for more fine-grained per-type processing.
     fn accept_discriminator_ref(&self, d: &mut impl DatumDiscriminatorRef)
     where
         Self: Sized,
@@ -53,41 +64,56 @@ pub trait Datum: Clone + std::fmt::Debug {
 /// to ensure [`QueryEquivalent`] can be implemented in the current Rust type system.
 pub trait ConcreteDatum: 'static + Datum {}
 
-/// Visitor for allowing for type-specific behaviour
+/// Visitor for allowing for type-specific behaviour.
 pub trait DatumDiscriminator {
+    /// Visit an `EntityID` type.
     fn visit_entity_id<E: Entity>(&mut self);
+    /// Visit a `Serialized<T>` instance.
     fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(&mut self);
+    /// Visit a bare datum field instance, such as a `String` or `usize`.
     fn visit_bare_field<T: Datum>(&mut self);
+    /// Visit a one-direction association map.
     fn visit_assoc_map<E: Entity>(&mut self);
+    /// Visit the domain side of a bidirectional relation map.
     fn visit_assoc_domain<R: Relation>(&mut self);
+    /// Visit the range side of a bidirectional relation map.
     fn visit_assoc_range<R: Relation>(&mut self);
 }
 
+/// Visitor for allowing for type-specific behaviour, with instances passed as references.
 pub trait DatumDiscriminatorRef {
+    /// Visit an `EntityID` instance.
     fn visit_entity_id<E: Entity>(&mut self, _: &E::ID);
+    /// Visit a `Serialized<T>` instance.
     fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(&mut self, _: &T);
+    /// Visit a bare datum field instance, such as a `String` or `usize`.
     fn visit_bare_field<T: Datum>(&mut self, _: &T);
+    /// Visit a one-direction association map instance.
     fn visit_assoc_map<E: Entity>(&mut self, _: &AssocMap<E>);
+    /// Visit an instance of the domain side of a bidirectional relation map.
     fn visit_assoc_domain<R: Relation>(&mut self, _: &AssocDomain<R>);
+    /// Visit an instance of the range side of a bidirectional relation map.
     fn visit_assoc_range<R: Relation>(&mut self, _: &AssocRange<R>);
 }
 
 /// A fixed-length list of EntityDatums, usually a tuple.
 pub trait DatumList: Clone {
+    /// Accept a datum visitor for iteration.
     fn accept(&self, visitor: &mut impl DatumVisitor);
-
-    const LEN: usize;
 }
 
 /// A list of concrete datums.
 pub trait ConcreteDatumList: DatumList + Clone {
+    /// Construct a [`DatumList`] that is _query-equivalent_ of the current type. See
+    /// [`QueryEquivalent`] and [`QueryEquivalentList`] for more information.
     fn build_equivalent<'l>(
         from: impl Iterator<Item = &'l str>,
     ) -> Option<impl QueryEquivalentList<Self> + 'l>;
 }
 
-/// A walker for a DatumList instance.
+/// A walker for DatumList instances.
 pub trait DatumVisitor {
+    /// Visit a specific datum in a DatumList.
     fn visit<ED: Datum>(&mut self, datum: &ED);
 }
 

+ 0 - 7
microrm/src/schema/datum/datum_list.rs

@@ -5,8 +5,6 @@ use super::{
 
 impl DatumList for () {
     fn accept(&self, _: &mut impl DatumVisitor) {}
-
-    const LEN: usize = 0;
 }
 impl ConcreteDatumList for () {
     fn build_equivalent<'l>(
@@ -22,8 +20,6 @@ impl<T: Datum> DatumList for T {
     fn accept(&self, visitor: &mut impl DatumVisitor) {
         visitor.visit(self);
     }
-
-    const LEN: usize = 1;
 }
 
 impl<T: ConcreteDatum> ConcreteDatumList for T {
@@ -40,8 +36,6 @@ impl<T0: Datum> DatumList for (T0,) {
     fn accept(&self, visitor: &mut impl DatumVisitor) {
         visitor.visit(&self.0);
     }
-
-    const LEN: usize = 1;
 }
 
 impl<T0: ConcreteDatum> ConcreteDatumList for (T0,) {
@@ -60,7 +54,6 @@ macro_rules! datum_list {
             fn accept(&self, visitor: &mut impl DatumVisitor) {
                 $(visitor.visit(&self. $n));*
             }
-            const LEN: usize = $len;
         }
 
         impl<$( $ty: ConcreteDatum, $e: QueryEquivalent<$ty> ),*> QueryEquivalentList<( $( $ty ),* )> for ( $( $e ),* ) {}

+ 32 - 2
microrm/src/schema/entity.rs

@@ -36,7 +36,7 @@ pub trait EntityPart: Default + Clone + 'static {
 
     /// String representing the field name.
     fn part_name() -> &'static str;
-    /// Whether this field has a #[unique] attribute or not.
+    /// Whether this field has a `#[unique]` attribute or not.
     fn unique() -> bool;
     /// Documentation comment for this field.
     fn desc() -> Option<&'static str>;
@@ -47,24 +47,40 @@ pub trait EntityPart: Default + Clone + 'static {
 
 /// Visitor for traversing all [`EntityPart`]s in an [`Entity`] or [`EntityPartList`].
 pub trait EntityPartVisitor {
+    /// The [`Entity`] that this visitor will traverse over the parts of.
     type Entity: Entity;
+    /// Visit a part, with no instance information.
     fn visit<EP: EntityPart<Entity = Self::Entity>>(&mut self) {}
+    /// Visit a part, with a datum reference.
     fn visit_datum<EP: EntityPart<Entity = Self::Entity>>(&mut self, _datum: &EP::Datum) {}
+    /// Visit a part, with a mutable datum reference.
     fn visit_datum_mut<EP: EntityPart<Entity = Self::Entity>>(&mut self, _datum: &mut EP::Datum) {}
 }
 
 /// List of EntityParts.
 pub trait EntityPartList: 'static {
+    /// The [`Entity`] that this list represents the parts of.
     type Entity: Entity;
+    /// A [`ConcreteDatumList`] type that matches this part list, formed as the `EntityPart::Datum`s of
+    /// each `EntityPart` in this list.
     type DatumList: ConcreteDatumList + QueryEquivalentList<Self::DatumList>;
 
-    type ListHead: EntityPart;
+    /// The first element of this list. If this list is empty, this will be a generic marker type
+    /// with poisoned values to be easily visible if processed.
+    type ListHead: EntityPart<Entity = Self::Entity>;
+    /// An [`EntityPartList`] that represents all but the first element of this list.
     type ListTail: EntityPartList<Entity = Self::Entity>;
+    /// Whether the current list is empty. Should be used to control recursion if iterating across
+    /// the list.
     const IS_EMPTY: bool = false;
 
+    /// Construct an instance of `Self::DatumList` from a table row.
     fn build_datum_list(conn: &Connection, stmt: &mut StatementRow) -> DBResult<Self::DatumList>;
 
+    /// Accept a visitor to iterate across each part in the list, with no datum instances.
     fn accept_part_visitor(_: &mut impl EntityPartVisitor<Entity = Self::Entity>);
+    /// Accept a visitor to iterate across each part in the list, with datum instances provided by
+    /// a `Self::DatumList` instance.
     fn accept_part_visitor_ref(
         datum_list: &Self::DatumList,
         _: &mut impl EntityPartVisitor<Entity = Self::Entity>,
@@ -74,6 +90,7 @@ pub trait EntityPartList: 'static {
 // trait implementations for EntityPartList
 mod part_list;
 
+/// A sentinel type representing a zero-length [`EntityPartList`].
 pub use part_list::EmptyList;
 
 // ----------------------------------------------------------------------
@@ -82,19 +99,32 @@ pub use part_list::EmptyList;
 
 /// A single database entity, aka an object type that gets its own table.
 pub trait Entity: 'static + std::fmt::Debug {
+    /// A list of all the [`EntityPart`]s that make up the fields of the struct.
     type Parts: EntityPartList<Entity = Self>;
+    /// A list of the [`EntityPart`]s that make up the list of access keys for the entity. Can be an
+    /// [`EmptyList`] if no keys are defined.
     type Keys: EntityPartList<Entity = Self>;
+    /// The corresponding [`EntityID`] type for this Entity.
     type ID: EntityID<Entity = Self> + EntityPart<Datum = Self::ID, Entity = Self>;
 
+    /// Construct an instance of this entity from a list of datums that matches each part, in
+    /// order.
     fn build(values: <Self::Parts as EntityPartList>::DatumList) -> Self;
 
+    /// A static string used as the database table name for the entity.
     fn entity_name() -> &'static str;
+    /// Accept a visitor to iterate across each part in the entity, with no datum instances.
     fn accept_part_visitor(visitor: &mut impl EntityPartVisitor<Entity = Self>);
+    /// Accept a visitor to iterate across each part in the entity, with datum instances pulled
+    /// from an instance of `Self`.
     fn accept_part_visitor_ref(&self, visitor: &mut impl EntityPartVisitor<Entity = Self>);
+    /// Accept a visitor to iterate across each part in the entity, with mutable datum instances
+    /// pulled from an instance of `Self`.
     fn accept_part_visitor_mut(&mut self, _: &mut impl EntityPartVisitor<Entity = Self>);
 }
 
 /// Visitor for traversing all [`Entity`]s in a container type.
 pub trait EntityVisitor {
+    /// Visit a particular entity.
     fn visit<E: Entity>(&mut self);
 }