Skip to main content

doublets/decorators/
builder.rs

1//! The builder that composes decorators into a single concrete type.
2
3use std::io::Write;
4
5use data::LinkReference;
6
7use super::{
8    policy::{UniquenessPolicy, UsagesPolicy},
9    CascadeUniquenessAndUsagesResolver, CascadeUsagesResolver, InnerReferenceExistenceValidator,
10    ItselfConstantToSelfReferenceResolver, LoggingDecorator, NoExceptionsDecorator,
11    NonExistentDependenciesCreator, NonNullContentsLinkDeletionResolver,
12    NullConstantToSelfReferenceResolver, UsagesValidator,
13};
14use crate::Doublets;
15
16/// The stack C# `ILinksExtensions.DecorateWithAutomaticUniquenessAndUsagesResolution`
17/// builds, spelled as a type.
18pub type AutomaticUniquenessAndUsagesResolution<T, L> = CascadeUniquenessAndUsagesResolver<
19    T,
20    NonNullContentsLinkDeletionResolver<T, CascadeUsagesResolver<T, L>>,
21>;
22
23/// Composes decorators around a store.
24///
25/// Every method takes the store by value and returns the *concrete* composed type, so a
26/// stack is built at compile time and every layer is a candidate for inlining:
27///
28/// ```rust
29/// use doublets::{decorators::{DecoratorsExt, Resolve}, mem, unit, Doublets};
30///
31/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
32/// let mut store = unit::Store::<usize, _>::new(mem::Global::new())?
33///     .with_uniqueness(Resolve)
34///     .with_usages_validation();
35///
36/// let a = store.create_point()?;
37/// let b = store.create_point()?;
38/// // The second `create_link` reuses the first one instead of storing a duplicate.
39/// assert_eq!(store.create_link(a, b)?, store.create_link(a, b)?);
40/// # Ok(())
41/// # }
42/// ```
43pub trait DecoratorsExt<T: LinkReference>: Doublets<T> + Sized {
44    /// Applies a [`UniquenessPolicy`] — [`Validate`](super::Validate),
45    /// [`Resolve`](super::Resolve) or [`CascadeResolve`](super::CascadeResolve).
46    #[inline]
47    fn with_uniqueness<P: UniquenessPolicy>(self, _policy: P) -> P::Decorator<T, Self> {
48        P::decorate(self)
49    }
50
51    /// Applies a [`UsagesPolicy`] — [`Validate`](super::Validate) or
52    /// [`CascadeResolve`](super::CascadeResolve).
53    #[inline]
54    fn with_usages<P: UsagesPolicy>(self, _policy: P) -> P::Decorator<T, Self> {
55        P::decorate(self)
56    }
57
58    /// Wraps in [`UsagesValidator`].
59    #[inline]
60    fn with_usages_validation(self) -> UsagesValidator<T, Self> {
61        UsagesValidator::new(self)
62    }
63
64    /// Wraps in [`CascadeUsagesResolver`].
65    #[inline]
66    fn with_cascade_usages_resolution(self) -> CascadeUsagesResolver<T, Self> {
67        CascadeUsagesResolver::new(self)
68    }
69
70    /// Wraps in [`InnerReferenceExistenceValidator`].
71    #[inline]
72    fn with_inner_reference_existence_validation(
73        self,
74    ) -> InnerReferenceExistenceValidator<T, Self> {
75        InnerReferenceExistenceValidator::new(self)
76    }
77
78    /// Wraps in [`NonExistentDependenciesCreator`].
79    #[inline]
80    fn with_non_existent_dependencies_creation(self) -> NonExistentDependenciesCreator<T, Self> {
81        NonExistentDependenciesCreator::new(self)
82    }
83
84    /// Wraps in [`ItselfConstantToSelfReferenceResolver`].
85    #[inline]
86    fn with_itself_constant_resolution(self) -> ItselfConstantToSelfReferenceResolver<T, Self> {
87        ItselfConstantToSelfReferenceResolver::new(self)
88    }
89
90    /// Wraps in [`NullConstantToSelfReferenceResolver`].
91    #[inline]
92    fn with_null_constant_resolution(self) -> NullConstantToSelfReferenceResolver<T, Self> {
93        NullConstantToSelfReferenceResolver::new(self)
94    }
95
96    /// Wraps in [`NonNullContentsLinkDeletionResolver`].
97    #[inline]
98    fn with_non_null_contents_deletion_resolution(
99        self,
100    ) -> NonNullContentsLinkDeletionResolver<T, Self> {
101        NonNullContentsLinkDeletionResolver::new(self)
102    }
103
104    /// Wraps in [`LoggingDecorator`], logging every mutation to `writer`.
105    #[inline]
106    fn with_logging<W: Write + Send + Sync>(self, writer: W) -> LoggingDecorator<T, Self, W> {
107        LoggingDecorator::new(self, writer)
108    }
109
110    /// Wraps in [`NoExceptionsDecorator`].
111    #[inline]
112    fn with_no_exceptions(self) -> NoExceptionsDecorator<T, Self> {
113        NoExceptionsDecorator::new(self)
114    }
115
116    /// Builds the same stack as C#
117    /// `ILinksExtensions.DecorateWithAutomaticUniquenessAndUsagesResolution`:
118    /// [`CascadeUsagesResolver`] innermost, then [`NonNullContentsLinkDeletionResolver`],
119    /// then [`CascadeUniquenessAndUsagesResolver`] outermost.
120    #[inline]
121    fn with_automatic_uniqueness_and_usages_resolution(
122        self,
123    ) -> AutomaticUniquenessAndUsagesResolution<T, Self> {
124        CascadeUniquenessAndUsagesResolver::new(NonNullContentsLinkDeletionResolver::new(
125            CascadeUsagesResolver::new(self),
126        ))
127    }
128}
129
130impl<T: LinkReference, L: Doublets<T>> DecoratorsExt<T> for L {}