daab/
lib.rs

1// Only warn about unsafe code in general (needed for some tests)
2#![warn(unsafe_code)]
3// If not in test mode, forbid it entirely!
4#![cfg_attr(not(test), forbid(unsafe_code))]
5
6// Enables casting of trait-objects behind a Can
7#![cfg_attr(feature = "unsized", feature(unsize))]
8
9// Enable annotating features requirements in docs
10#![cfg_attr(feature = "doc_cfg", feature(doc_cfg))]
11
12// prevents compilation with broken Deref impl causing nasty stack overflows.
13#![deny(unconditional_recursion)]
14
15// Ensures that `pub` means published in the public API.
16// This property is useful for reasoning about breaking API changes.
17#![deny(unreachable_pub)]
18
19// Prevents public API entries without a doc comment.
20#![warn(missing_docs)]
21
22
23//!
24//! DAG Aware Artifact Builder
25//! ==========================
26//!
27//! Rust crate for managing the building and caching of artifacts which are
28//! connected in a directed acyclic graph (DAG) like manner, i.e. artifacts may
29//! depend on others.
30//!
31//! The caching provided by this crate could be especially useful if the
32//! artifact builders use consumable resources, the building process is a
33//! heavyweight procedure, or a given DAG dependency structure among the
34//! builders shall be properly preserved among their artifacts.
35//!
36//! Minimal Rust version: **1.40**
37//!
38//!
39//!
40//! ## Basic Concept
41//!
42//! The basic concept of daab revolves around _Builders_, which are user provided
43//! structs that implement the [`Builder`] trait. That trait essentially has an
44//! associated type [`Artifact`] and method [`build`] where the latter will
45//! produce a value of the `Artifact` type, which will be subsequently be
46//! referred to as _Artifact_. In order to be able to depend on the Artifact of
47//! other Builders, the `build` method also gets a [`Resolver`] that allows
48//! to retrieve the Artifacts of others.
49//!
50//! In order to allow Builders and Artifacts to form a directed acyclic graph
51//! this crate provides at its heart an Artifact [`Cache`] which keeps the
52//! Artifacts of Builders in order to prevent the Builders to produce multiple
53//! equal Artifacts. Thus different Builders may depend on same Builder and
54//! getting the same Artifact from the `Cache`.
55//!
56//! To be able to share Builders and Artifacts this crate also provides a
57//! concept of _Cans_ and _Bins_, which in the most basic case are simply an opaque
58//! `Rc<dyn Any>` and a transparent `Rc<T>`, respectively. These are referred to
59//! by the generic arguments of e.g. the `Cache`. For more details consult the
60//! [`canning`] module.
61//!
62//! Additional to the canning, the `Cache` expects Builders to wrapped in a
63//! opaque [`Blueprint`] enforcing encapsulation, i.e. it prevents users from
64//! accessing the inner struct (the one which implements the `Builder` trait),
65//! while only allowing the `Cache` itself to call its `build` method.
66//!
67//!
68//!
69//! ### Getting started
70//!
71//! For the basic concept (explained above) there exists simplified traits
72//! which skip over the more
73//! advanced features. One such simplified trait is the [`SimpleBuilder`] of the
74//! [`rc`] module, which uses `Rc`s for canning and has simplified aliases
75//! (minimal generic arguments) for all the above types. For getting started
76//! that `rc` module is probably the best place to start.
77//!
78//!
79//!
80//! ## Detailed Concept
81//!
82//! See the [Advanced Feature section of `Builder`].
83//!
84//! Also see [`Cache`], [`Builder`], [`blueprint`], [`canning`]
85//!
86//!
87//![`Builder`]: trait.Builder.html
88//![`Artifact`]: trait.Builder.html#associatedtype.Artifact
89//![`build`]: trait.Builder.html#tymethod.build
90//![`SimpleBuilder`]: rc/trait.SimpleBuilder.html
91//![`rc`]: rc/index.html
92//![`canning`]: canning/index.html
93//![`blueprint`]: blueprint/index.html
94//![`Blueprint`]: blueprint/struct.Blueprint.html
95//![`Resolver`]: cache/struct.Resolver.html
96//![`Cache`]: cache/struct.Cache.html
97//![Advanced Feature section of `Builder`]: trait.Builder.html#advanced-features
98//!
99//!
100//! ## Example
101//!
102//! ```rust
103//! use std::rc::Rc;
104//! use daab::*;
105//!
106//! // Simple artifact
107//! #[derive(Debug)]
108//! struct Leaf {
109//!     //...
110//! }
111//!
112//! // Simple builder
113//! #[derive(Debug)]
114//! struct BuilderLeaf {
115//!     // ...
116//! }
117//! impl BuilderLeaf {
118//!     pub fn new() -> Self {
119//!         Self {
120//!             // ...
121//!         }
122//!     }
123//! }
124//! impl rc::SimpleBuilder for BuilderLeaf {
125//!     type Artifact = Leaf;
126//!
127//!     fn build(&self, _resolver: &mut rc::Resolver) -> Self::Artifact {
128//!         Leaf{
129//!             // ...
130//!         }
131//!     }
132//! }
133//!
134//! // Composed artifact, linking to a Leaf
135//! #[derive(Debug)]
136//! struct Node {
137//!     leaf: Rc<Leaf>, // Dependency artifact
138//!     value: u8, // Some custom value
139//!     // ...
140//! }
141//!
142//! // Composed builder, depending on BuilderLeaf
143//! #[derive(Debug)]
144//! struct BuilderNode {
145//!     builder_leaf: rc::Blueprint<BuilderLeaf>, // Dependency builder
146//!     // ...
147//! }
148//! impl BuilderNode {
149//!     pub fn new(builder_leaf: rc::Blueprint<BuilderLeaf>) -> Self {
150//!         Self {
151//!             builder_leaf,
152//!             // ...
153//!         }
154//!     }
155//! }
156//! use std::any::Any;
157//! impl rc::Builder for BuilderNode {
158//!     type Artifact = Node;
159//!     type DynState = u8;
160//!     type Err = Never;
161//!
162//!     fn build(&self, resolver: &mut rc::Resolver<Self::DynState>) -> Result<Rc<Self::Artifact>, Never> {
163//!         // Resolve Blueprint to its artifact
164//!         // Unpacking because the Err type is Never.
165//!         let leaf = resolver.resolve(&self.builder_leaf).unpack();
166//!
167//!         Ok(Node {
168//!             leaf,
169//!             value: *resolver.my_state(),
170//!             // ...
171//!         }.into())
172//!     }
173//!     fn init_dyn_state(&self) -> Self::DynState {
174//!         42
175//!     }
176//! }
177//!
178//! // The cache to storing already created artifacts
179//! let mut cache = rc::Cache::new();
180//!
181//! // Constructing builders
182//! let leaf_builder = rc::Blueprint::new(BuilderLeaf::new());
183//!
184//! let node_builder_1 = rc::Blueprint::new(BuilderNode::new(leaf_builder.clone()));
185//! let node_builder_2 = rc::Blueprint::new(BuilderNode::new(leaf_builder.clone()));
186//!
187//! // Using the cache to access the artifacts from the builders
188//!
189//! // The same builder results in same artifact
190//! assert!(Rc::ptr_eq(&cache.get(&node_builder_1).unpack(), &cache.get(&node_builder_1).unpack()));
191//!
192//! // Different builders result in different artifacts
193//! assert!( ! Rc::ptr_eq(&cache.get(&node_builder_1).unpack(), &cache.get(&node_builder_2).unpack()));
194//!
195//! // Different artifacts may link the same dependent artifact
196//! assert!(Rc::ptr_eq(&cache.get(&node_builder_1).unpack().leaf, &cache.get(&node_builder_2).unpack().leaf));
197//!
198//! // Purge builder 2 to ensure the following does not affect it
199//! cache.purge(&node_builder_2);
200//!
201//! // Test dynamic state
202//! assert_eq!(cache.get(&node_builder_1).unpack().value, 42);
203//!
204//! // Change state
205//! *cache.dyn_state_mut(&node_builder_1) = 127.into();
206//! // Without invalidation, the cached artefact remains unchanged
207//! assert_eq!(cache.dyn_state(&node_builder_1), &127);
208//! // Invalidate node, and ensure it made use of the state
209//! assert_eq!(cache.get(&node_builder_1).unpack().value, 127);
210//!
211//! // State of node 2 remains unchanged
212//! assert_eq!(cache.get_dyn_state(&node_builder_2), None);
213//! assert_eq!(cache.get(&node_builder_2).unpack().value, 42);
214//! ```
215//!
216//!
217//!
218//! ## Debugging
219//!
220//! `daab` comes with extensive debugging gear. However, in order to
221//! keep the production impact as low as possible, the debugging facilities
222//! are capsuled behind the **`diagnostics`** feature.
223//!
224//! Of course, the debugging feature is for the user of this crate to
225//! debug their graphs. Therefore, it is rather modelled as a
226//! diagnostics feature (hence the name). The diagnosis
227//! is carried out by a [`Doctor`], which is a trait receiving various
228//! internal events in order to record them, print them, or otherwise help
229//! treating the bug.
230//!
231//! Care has been taken to keep the **`diagnostics`** feature broadly applicable
232//! as well as keeping the non-`diagnostics` API compatible with the
233//! `diagnostics`-API, meaning that a project not using the
234//! `diagnostics` feature can be easily converted to using
235//! `diagnostics`, usually by just replacing `Cache::new()`
236//! with `Cache::new_with_doctor()`.
237//! In order to store the `Doctor` the `Cache` is generic to a doctor,
238//! which is important on its creation and for storing it by value.
239//! The rest of the time the `Cache` uses `dyn Doctor` as its default
240//! generic argument.
241//! To ease conversion between them, all creatable `Cache`s
242//! (i.e. not `Cache<dyn Doctor>`) implement `DerefMut` to
243//! `&mut Cache<dyn Doctor>` which has all the important methods
244//! implemented.
245//!
246//![`Doctor`]: diagnostics/trait.Doctor.html
247//!
248//!
249//!
250//! ## Features
251//!
252//! This crate offers the following features:
253//!
254//! - **`diagnostics`** enables elaborate graph and cache interaction debugging.
255//!   It adds the `new_with_doctor()` function to the `Cache` and adds
256//!   the `diagnostics` module with the `Doctor` trait definition and some
257//!   default `Doctor`s.
258//!
259//! - **`tynm`** enable the optional dependency on the [`tynm`] crate which adds
260//!   functionality to abbreviate type names, which are used by some default
261//!   `Doctor`s, hence it is only useful in connection with the `diagnostics`
262//!   feature.
263//!
264//! - **`unsized`** enables better conversion between unsized Builders with
265//!   [`BlueprintUnsized::into_unsized`]. **This feature requires Nightly
266//!   Rust**.
267//!
268//![`tynm`]: https://crates.io/crates/tynm
269//![`BlueprintUnsized::into_unsized`]: blueprint/struct.BlueprintUnsized.html#method.into_unsized
270//!
271
272
273
274use std::any::Any;
275use std::hash::Hash;
276use std::fmt;
277use std::fmt::Debug;
278
279use cfg_if::cfg_if;
280
281pub mod rc;
282pub mod arc;
283pub mod boxed;
284
285pub mod blueprint;
286pub mod canning;
287pub mod cache;
288pub mod utils;
289
290use canning::Can;
291use canning::CanStrong;
292use canning::CanBuilder;
293use canning::CanSized;
294use canning::CanRef;
295use canning::CanRefMut;
296
297use blueprint::Promise;
298use blueprint::Blueprint;
299use blueprint::BlueprintDyn;
300use cache::Cache;
301use cache::CacheOwned;
302use cache::Resolver;
303
304cfg_if! {
305	if #[cfg(feature = "unsized")] {
306		use canning::CanUnsized;
307	}
308}
309
310#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "diagnostics")))]
311#[cfg(feature = "diagnostics")]
312pub mod diagnostics;
313
314cfg_if! {
315	if #[cfg(feature = "diagnostics")] {
316		use diagnostics::Doctor;
317		use diagnostics::ArtifactHandle;
318		use diagnostics::BuilderHandle;
319		use diagnostics::NoopDoctor as DefDoctor;
320	}
321}
322
323/// `daab`s Prelude.
324///
325/// This module contains some traits which are useful to be in scope. Just
326/// write in your code:
327///
328/// ```rust
329/// use daab::prelude::*;
330/// ```
331///
332pub mod prelude {
333	pub use crate::Unpacking as _;
334	pub use crate::blueprint::Promise as _;
335}
336
337
338// Pub-use the Never type of the never crate.
339pub use never::Never;
340
341/// Unpack a result into its value.
342fn unpack<T>(res: Result<T,Never>) -> T {
343    match res {
344        Ok(t) => t,
345        Err(n) => match n {},
346    }
347}
348
349/// Unpacking a composite type into its inner value.
350///
351/// This trait is use in contexts where [`Never`] appears. For instance this
352/// trait is implemented on `Result<T,Never>` to unpack `T`, which is its only
353/// value as `Never` is uninhabited i.e. can never exist.
354///
355/// One can think about unpacking as a compile-time guaranteed non-panicking
356/// alternative to unwrapping. Therefore, if unpacking is available it should
357/// be preferred over unwrapping.
358///
359/// # Example
360///
361/// ```
362/// use daab::Never;
363/// use daab::Unpacking;
364///
365/// let res: Result<u32, Never> = Ok(42);
366/// // The error Never can never exist, thus we can unpack the result directly
367/// // into the u32, compile-time guaranteed panic-free.
368/// assert_eq!(42, res.unpack())
369/// ```
370///
371/// [`Never`]: enum.Never.html
372///
373pub trait Unpacking {
374	/// The type to be unpacked.
375    type Inner;
376
377	/// Unpacking into its inner value.
378	///
379	/// This function is guaranteed to never fail nor panic.
380	///
381    fn unpack(self) -> Self::Inner;
382}
383impl<T> Unpacking for Result<T,Never> {
384    type Inner = T;
385
386    fn unpack(self) -> T {
387        unpack(self)
388    }
389}
390
391
392
393/// Represents a Builder for an Artifact.
394///
395/// The `Builder` is the central trait of this crate. It defines the
396/// _Builders_ (the structs implementing this trait) which are referred to
397/// throughout this crate, as well as the _Artifacts_, which are the values
398/// build by a Builder, and defined via the [`Artifact`] associate type.
399///
400/// To be usable within this crate, a Builder has to be wrapped in a
401/// [`Blueprint`]. Then it can be used to with a [`Cache`] to build and get
402/// its Artifact.
403///
404/// When `Blueprint` (containing a `Builder`) is resolved at a `Cache`, the
405/// `Cache` will call the [`build`] method of that `Builder` as needed (i.e.
406/// whenever there is no cached Artifact available),
407/// providing it with a [`Resolver`], which allows to resolve its depending
408/// Builders to their Artifacts.
409///
410/// An important concept is that a Builder may depend on other Builders (i.e.
411/// it may use their Artifacts to construct its own Artifact). Thus constituting
412/// existential dependencies between Artifacts.
413/// The depending Builders are supposed to be stored in the `Builder` struct
414/// which is then accessible from the `build` method to resolve them.
415///
416///
417///
418/// # Advanced Features
419///
420/// Unlike various `SimpleBuilder`s this `Builder` offers additionally more
421/// advanced features than described above. These are explained in the
422/// following.
423///
424///
425/// ## Dynamic State
426///
427/// Each `Builder` may define a dynamic state, default is the unit type `()`.
428/// That is a value that will be stored in a `Box` in the `Cache`, which will
429/// be accessible even mutably for anyone from the `Cache`, as opposed to the
430/// `Builder` itself, which will become inaccessible once wrapped in a
431/// `Blueprint`.
432///
433/// If a `Builder` is encountered by a `Cache` for the first time, the `Cache`
434/// will use the `Builder`'s `init_dyn_state` method to initialize the stored
435/// dynamic state. It can then be accessed by the `Builder` itself from its
436/// `build` method thought [`Resolver::my_state`] of the provided `Resolver`.
437///
438/// The dynamic state might be used for various purposes, the simples is as a
439/// kind of variable configuration of the respective `Builder`. Notice that the
440/// Artifact conceptional depends on the dynamic state, thus altering the
441/// dynamic state (i.e. if access thought [`Cache::dyn_state_mut`])
442/// will invalidate the Artifact of the respective `Builder`.
443///
444/// Another use-case of the dynamic state is to keep some state between builds.
445/// An extreme example of this is the [`RedeemingBuilder`], which will replay
446/// entire Artifacts of its inner Builder, when it fails to produce a new one.
447///
448///
449/// ## Failure
450///
451/// `Builder`s are generally allowed to fail. Thus returning a `Result`
452/// with the defined [`Err`] type,
453/// which can be returned by the `build` method.
454///
455/// The infallible `SimpleBuilder`s use the [`Never`]-type (a stable variation
456/// of the yet unstable `!`, the official `never`-type) as `Err`, because that
457/// `Never` type allows simple [unpacking] of the `Result`s returned by the
458/// `Cache`.
459/// Thus if a Builder can always produce an Artifact, its `Err` type should be
460/// that [`Never`] type.
461///
462///
463///
464/// [`Artifact`]: trait.Builder.html#associatedtype.Artifact
465/// [`Blueprint`]: blueprint/struct.Blueprint.html
466/// [`Cache`]: cache/struct.Cache.html
467/// [`build`]: trait.Builder.html#tymethod.build
468/// [`Resolver`]: cache/struct.Resolver.html
469/// [`Resolver::my_state`]: cache/struct.Resolver.html#method.my_state
470/// [`Cache::dyn_state_mut`]: cache/struct.Cache.html#method.dyn_state_mut
471/// [`RedeemingBuilder`]: utils/struct.RedeemingBuilder.html
472/// [`Never`]: enum.Never.html
473/// [`Err`]: trait.Builder.html#associatedtype.Err
474/// [unpacking]: trait.Unpacking.html
475///
476pub trait Builder<ArtCan, BCan>: Debug + 'static
477		where
478			BCan: CanStrong, {
479
480	/// The artifact type as produced by this builder.
481	///
482	type Artifact : Debug + 'static;
483
484	/// Type of the dynamic state of this builder.
485	///
486	/// The dynamic state can be used to store mutable data for the builder
487	/// or to modify the builder for outside.
488	///
489	type DynState : Debug + 'static;
490
491	/// Error type returned by this Builder in case of failure to produce an
492	/// Artifact.
493	type Err : Debug + 'static;
494
495	/// Produces an artifact using the given `Resolver` for resolving
496	/// dependencies.
497	///
498	fn build(&self, cache: &mut Resolver<ArtCan, BCan, Self::DynState>)
499		-> Result<ArtCan::Bin, Self::Err>
500		where
501			ArtCan: Can<Self::Artifact>;
502
503	/// Return an initial dynamic state for this builder.
504	///
505	/// When a builder is first seen by a `Cache` the cache will use this method
506	/// to obtain an initial value for the dynamic state of this builder.
507	///
508	fn init_dyn_state(&self) -> Self::DynState;
509}
510
511
512
513/// Id to differentiate builder instances across types.
514///
515/// Notice, this type simply wraps `*const` to the builder `Rc`s.
516/// Consequentially, a `BuilderId`s validity is limited to the life time of
517/// the respective `Builder`.
518///
519#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
520pub struct BuilderId(usize);
521
522impl BuilderId {
523	fn new(ptr: *const dyn Any) -> Self {
524		BuilderId(ptr as *const () as usize)
525	}
526
527	fn as_ptr(&self) -> *const () {
528		self.0 as *const ()
529	}
530}
531
532impl fmt::Pointer for BuilderId {
533	fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
534		fmt::Pointer::fmt(&self.as_ptr(), fmt)
535	}
536}
537
538
539
540// -----------
541
542#[cfg(test)]
543mod test;
544
545//#[cfg(test)]
546//mod multi_level_test;
547
548
549
550
551