1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//!
#![cfg_attr(feature = "doc-images",
  cfg_attr(all(),
    doc = ::embed_doc_image::embed_image!("roopes-logo", "src/logo.svg")
  ))]
#![cfg_attr(
    not(feature = "doc-images"),
    doc = "**Doc images not enabled**. Compile with feature `doc-images` and \
           Rust version >= 1.54 to enable."
)]
#![deny(
    clippy::pedantic,
    clippy::style,
    clippy::correctness,
    clippy::complexity
)]
//! ![roopes logo][roopes-logo]
//!
//! Roopes is a Rust Object Oriented Pattern Element System.
//! This crate provides generic traits and implementations for typical
//! object-oriented patterns in Rust. It is intended to be used as a cluster of
//! utility classes for implementing OOP-architected executables -- *in
//! Rust!*.
//!
//! ## Goals
//! This package intends to meet the following criteria:
//! - Provide implementations of common OOP Design Patterns usable to compose
//!   larger programs.
//! - Document and implement reference implementations for students of OOP and
//!   Rust.
//! - Be easy to use for those familiar with the corresponding patterns.
//!
//! ## Optimization as a Non-Goal
//! It is convenient that Rust can produce low-level, optimized code.
//! On the other hand, optimizing for execution speed can conflict with the
//! maintainability of a system. Traits provided should give
//! zero-cost-abstractions while possible. However, working with v-tables has an
//! inherent (though small) cost, so when it comes to the provided
//! implementations, no guarantees about speed are provided.
//!
//! It has also been observed that the use of `dyn` is inherently less efficient
//! in Rust due to the inability for the compiler to see the indirected code in
//! the client code, eliminating a good number of optimizations the compiler
//! would otherwise be able to use on client code, probably resulting in less
//! optimized builds. `dyn` should occur in the provided traits, but
//! implementations often use it (e.g: `Box` or `Vec`).
//!
//! ## Usage
//! To install, add the
//! crate to your `cargo.toml` as usual. The types provided are minimal, but the
//! provided implementations should facilitate the most common uses.
//! `use roopes::prelude::*` will expose the essential traits. Implementations
//! are **not** exposed through `prelude` -- to use them, the
//! specific implementation must be referenced in their module, such as
//! `roopes::patterns::builder::Lambda`. To mitigate manually importing a large
//! number of implementations, roopes re-exports submodules which should make
//! the direct referencing of these types easier and more hygienic. In this
//! example, [`roopes_core::patterns::command::heap::Heap`] is re-used directly
//! from the [`prelude`] import.  E.g.:
//! ``` rust
//! use roopes::prelude::*;
//! let command = command::Heap::from(|| {
//!     {
//!         println!("Hello world!");
//!     }
//!     .into()
//! });
//! command.execute();
//! ```
//!
//! # Provided Patterns
//! Traits describing patterns are placed in one of three categories:
//! ## Primitives
//! These modules form the basis of re-used abstractions used by patterns.
//! These types exist to unify the syntax of the system: as a general rule, each
//! pattern contains a central group of traits made generic on some
//! user-specified type. e.g.: A builder is generic on the type on which
//! `build()` produces.
//! [Please don't @ me.](https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)
//!
//! These types supply each of the following scenarios:
//!
//! | Type | Receives Value | Produces Value |
//! |--------|------------------|------------------|
//! | [`roopes_core::primitives::executable::Executable`] | No | No |
//! | [`roopes_core::primitives::emitter::Emitter`] | No | Yes |
//! | [`roopes_core::primitives::handler::Handler`] | Yes | No |
//! | [`roopes_core::primitives::transformer::Transformer`] | Yes | Yes |
//!
//! They can be used independently, but don't necessarily conform to a more
//! widely-accepted pattern other than various forms of `dyn Fn`, so that may
//! lead to undesirable qualities in your project if used directly.
//!
//! ## Patterns
//! The more generally accepted patterns.
//!
//! - [`roopes_core::patterns::abstract_factory`]
//! Defines a method of creating typed objects.
//! - [`roopes_core::patterns::command::Command`]
//! Encapsulates a block of executable code.
//! - [`roopes_core::patterns::heap_pool::HeapPool`]
//! Reduces heap thrashing.
//! - [`roopes_core::patterns::observer`]
//! Manages the distribution of notifications.
//! - [`roopes_core::patterns::publisher_subscriber`]
//! Dynamically receive messages.
//! - [`roopes_core::patterns::state`]
//! Manages a discreet-state algorithm.
//! - [`roopes_core::patterns::transformer_chain`]
//! Aids in creating multi-stage, type-safe, data transformations.
//! - [`roopes_derive::Builder`]
//! Aids in the configuration and construction of similar objects.
//! - [`roopes_derive::PubSub`]
//! Simplified subscriber dispatch type generation on a type.
//! - [`roopes_derive::Visitor`]
//! Ensures a type can consume a message type.
//!
//! ## Aggregates
//! These patterns build on the common and primitive
//! functions to provide bridges between patterns. E.g: `Command` and the
//! primitive `Executable` correspond closely, so a bridge struct which
//! implements `Executable` for `Command`. These are provided to make the case
//! of moving between the given traits simpler, most often by calling `.into`.
//!
//! - [`roopes_core::aggregates::command_executable`]
//! Adapts `Command` from `Executable`.
//! - [`roopes_core::aggregates::executable_command`]
//! Adapts `Executable` from `Command`.
//! - [`roopes_core::aggregates::executable_observer`]
//! Adapts `Executable` from `Observer`.
//! - [`roopes_core::aggregates::handling_publisher`]
//! Adapts `Handler` from `Publisher`.
//! - [`roopes_core::aggregates::observing_command`]
//! Adapts `Observer` from `Command`.
//! - [`roopes_core::aggregates::subscribing_handler`]
//! Adapts `Subscriber` from `Handler`.
//! - [`roopes_core::aggregates::transforming_handler`]
//! Adapts `Transformer` from `Handler`.
//!
//! # Examples
//! ## lambda-logger
//! Demonstrates a stateful, functional-style logger system of a contrived
//! logging system.
//!
//! ## structuted-logger
//! Demonstrates a decoupled logging system.
//!
//! ## collision-simulator
//! Demonstrates an enum-based visitor-based system.
//!
//! # A Note on Issues
//! Issues in this project are
//! tracked with the system itself, not via an integrated tool, such as GitHub.
//! This enables issues to be tied to the state of the repo.
//! It may be beneficial to factor out issues into a separate repository for
//! some independence, but necessitating a particular tool is unhealthy for the
//! portability of this project.
//! Issues are currently tracked in the `issues.md` in the root of the main
//! project.
//!
//! # Dependencies
//! - `delegate` used to minimize boilerplate.
//! In particular, Rust does not have a trait inheritance system, so inheritance
//! (where appropriate) needs to be implemented manually. The `delegate!` macro
//! enables these streamlined implementations
//! - `enclose` This package is
//! used to simplify the process of copying reference-counted objects to and
//! from lambdas.
//!
//! # Addenda
//! ## OOP in Rust?  Are you crazy!?
//! Maybe a little, but...
//! Once you accept the speed impact `Rc<...>` incurs,
//! especially if the client algorithms are organized for memory locality, it's
//! really not that bad. Client code should also try to organize by sub-system -
//! if the borrow checker is involved, it's a good idea to try and observer a
//! sort of system-level coherence. In essence: if code is large enough to
//! require OOP, it's probably at a point in its lifecycle where development
//! time is incurring more cost than runtime.
//!
//! ## Why tho?
//! Rust's type system is a good compromise between safety and usability.
//! Architecting large systems without patterns can lead to
//! difficult-to-maintain software. It is also that some patterns here will open
//! possibilities for bugs that could be avoided by more directly using Rust's
//! type-system. This library attempts compromise to leverage the patterns OOP
//! gives us, to enable larger projects, but also have Rust's type-system and
//! borrow checker on hand.
#![feature(trait_alias)]
#![feature(associated_type_bounds)]
#![allow(unused_imports)]
#[macro_use]
extern crate roopes_derive;
extern crate roopes_core;

/// The building blocks for patterns and aggregates.
pub mod primitives
{
    pub use roopes_core::primitives::*;
}

/// Object oriented patterns.
pub mod patterns
{
    pub use roopes_core::patterns::*;
    pub use roopes_derive::*;
}

/// Methods of transmuting between patterns.
pub mod aggregates
{
    pub use roopes_core::aggregates::*;
}

/// Exposes the most used types from the library.
pub mod prelude
{
    pub use roopes_core::prelude::*;
    pub use roopes_derive::*;
}