Skip to content

Commit

Permalink
Update documentation of partial object API
Browse files Browse the repository at this point in the history
  • Loading branch information
hannobraun committed Sep 28, 2022
1 parent c763996 commit 2e274e2
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 31 deletions.
25 changes: 22 additions & 3 deletions crates/fj-kernel/src/partial/maybe_partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ use crate::{

use super::{HasPartial, Partial};

/// Either a partial object or a full one
/// Can be used everywhere either a partial or full objects are accepted
///
/// Some convenience methods are available for specific instances of
/// `MaybePartial` (like, `MaybePartial<Curve>`, or `MaybePartial<Vertex>`).
///
/// # Implementation Note
///
/// The set of available convenience methods is far from complete. Please feel
/// free to just add more, if you need them.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum MaybePartial<T: HasPartial> {
/// A full object
Expand All @@ -19,6 +27,10 @@ pub enum MaybePartial<T: HasPartial> {

impl<T: HasPartial> MaybePartial<T> {
/// If this is a partial object, update it
///
/// This is useful whenever a partial object can infer something about its
/// parts from other parts, and wants to update what was inferred, in case
/// it *can* be updated.
pub fn update_partial(
self,
f: impl FnOnce(T::Partial) -> T::Partial,
Expand All @@ -29,15 +41,22 @@ impl<T: HasPartial> MaybePartial<T> {
}
}

/// Return the full object, either directly or by building it
/// Return or build a full object
///
/// If this already is a full object, it is returned. If this is a partial
/// object, the full object is built from it, using [`Partial::build`].
pub fn into_full(self, stores: &Stores) -> T {
match self {
Self::Partial(partial) => partial.build(stores),
Self::Full(full) => full,
}
}

/// Return the partial object, either directly or via conversion
/// Return or convert a partial object
///
/// If this already is a partial object, is is returned. If this is a full
/// object, it is converted into a partial object using
/// [`HasPartial::to_partial`].
pub fn into_partial(self) -> T::Partial {
match self {
Self::Partial(partial) => partial,
Expand Down
61 changes: 35 additions & 26 deletions crates/fj-kernel/src/partial/mod.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
//! Partial objects
//!
//! This module contains type that represent partial objects. This is useful
//! when building objects, as it's often possible to provide just some the data
//! they own or objects they reference, while computing the rest.
//!
//! More generally speaking, there are situations where different parts of a new
//! objects are available at different times, and provided from different
//! places. Partial objects can be used to represent such partially constructed
//! objects whenever that is required.
//!
//! The API for partial objects follows a specific style:
//!
//! - Partial objects are structs with fields that mirror the fields of the full
//! object structs, but all fields are optional.
//! - Partial object structs implement [`Default`], but a `partial` method is
//! also available on the respective full object struct, as a perhaps more
//! convenient and readable way to construct a partial object.
//! - Partial object structs have `with_*` methods to provide values for each of
//! their fields.
//! - Partial object structs may have other methods with prefixes like `as_*`,
//! `from_*`, or similar, if one or more of their fields can be initialized by
//! providing alternative data.
//! - Partial object structs have a `build` method to build a full object.
//! - All `with_*`, `as_*`, and `build` methods can be chained, to provide a
//! convenient API.
//! API for dealing with partially defined objects
//!
//! This module contains types that represent objects that only have some of
//! their data and referenced objects defined. This is useful in the following
//! situations:
//!
//! - Sometimes parts of an object can be inferred. For example, when building a
//! half-edge that is a line segment, it is enough to provide only two partial
//! vertices with only their surface coordinates defined. The rest can be
//! inferred.
//! - Sometimes you need to build an object, but parts of it already exist. For
//! example, a new half-edge might share a vertex with an existing half-edge.
//! In such a case you can use the partial object to provide the existing
//! vertex, then provide or infer other parts as appropriate.
//! - When transforming an object, parts of it might already be transformed. For
//! example, when transforming a half-edge, each of its vertices references
//! the same curve as the half-edge does. The partial object API can be used
//! to avoid transforming the same object multiple times.
//!
//! This module contains two groups of types:
//!
//! - Structs that represent partial objects. For example [`PartialHalfEdge`] is
//! the partial variant of [`HalfEdge`].
//! - Infrastructure for abstracting over partial objects. See [`Partial`],
//! [`HasPartial`], and [`MaybePartial`].
//!
//! [`HalfEdge`]: crate::objects::HalfEdge
//!
//! # Implementation Note
//!
//! This API grew out of the [builder API][crate::builder] and is still
//! incomplete. Eventually, it should replace the builder API completely
//! ([#1147]).
//!
//! [#1147]: https://github.com/hannobraun/Fornjot/issues/1147

mod maybe_partial;
mod objects;
Expand Down
17 changes: 15 additions & 2 deletions crates/fj-kernel/src/partial/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::stores::Stores;

/// Implemented for types that are partial objects
/// Implemented for objects that a partial object type exists for
///
/// # Implementation Note
///
Expand All @@ -17,7 +17,7 @@ use crate::stores::Stores;
/// [#1021]: https://github.com/hannobraun/Fornjot/issues/1021
/// [`MaybePartial`]: super::MaybePartial
pub trait HasPartial {
/// The full version of this partial object
/// The type representing the partial variant of this object
type Partial: Partial<Full = Self>;

/// Create an empty partial variant of this object
Expand All @@ -40,6 +40,19 @@ pub trait HasPartial {

/// Implemented for partial objects
///
/// The API for partial objects follows a specific style:
///
/// - Partial objects are structs with fields that mirror the fields of the full
/// object structs, but all fields are optional.
/// - Partial object structs have `with_*` methods to provide values for each of
/// their fields.
/// - Partial object structs may have other methods with prefixes like `as_*`,
/// `from_*`, or similar, if one or more of their fields can be initialized by
/// providing alternative data.
/// - Partial object structs have a `build` method to build a full object.
/// - All `with_*`, `as_*`, and `build` methods can be chained, to provide a
/// convenient API.
///
/// # Implementation Note
///
/// It would be nicer to require an [`Into`] bound instead of [`From`] (see
Expand Down

0 comments on commit 2e274e2

Please sign in to comment.