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
//! Conflagrate is a framework for building applications from control flow graphs, instead of
//! the other way around.
//!
//! Conflagrate is designed to bring modularity, maintainability, and extensibility to control flow
//! logic. Where object oriented design, functional programming, dependency injection, and similar
//! tools help developers build and reuse functionality, conflagrate helps developers to encapsulate
//! that functionality in modular, testable building blocks that can be arranged and rearranged to
//! construct a complete application. Importantly, this application's control flow can be easily
//! updated to change the order of operations, conditions of branch execution, or even to add
//! entirely new subsystems without needing to refactor existing components or control flow.
//!
//! The control flow graph is defined with the [`graph`] macro, which converts your graph as
//! defined with the [DOT language](https://graphviz.org) into an executable structure. Each
//! node in the graph is annotated with a [`nodetype`] that associates a block of code with the
//! node. Finally, sometimes a node needs more to do its job than just the output of the previous
//! node in the graph. Conflagrate provides a simple dependency injection system to provide
//! external resources and data. Define a dependency provider function with the [`dependency`]
//! macro and add a reference to the dependency to the [`nodetype`] function signature.
//!
//! # Examples
//!
//! A simple program to record console inputs on a loop and echo them all back on exit:
//! ```no_run
//! # use tokio::sync::Mutex;
//! # use conflagrate::{dependency, graph, nodetype};
//! #
//! #[dependency]
//! async fn memory() -> Mutex<Vec<String>> {
//! Mutex::new(Vec::<String>::new())
//! }
//!
//! #[nodetype]
//! pub fn GetInput() -> String {
//! let mut input = String::new();
//! println!("Type any input ('exit' to exit):");
//! std::io::stdin().read_line(&mut input).unwrap();
//! input.truncate(input.len() - 1);
//! input
//! }
//!
//! #[nodetype]
//! async fn Record(input: String, memory: &Mutex<Vec<String>>) -> (String, ()) {
//! memory.lock().await.push(input.clone());
//! (input, ())
//! }
//!
//! #[nodetype]
//! pub async fn EchoAndExit(memory: &Mutex<Vec<String>>) {
//! println!("You entered:");
//! let inputs = memory.lock().await;
//! for input in inputs.iter() {
//! println!("{}", input);
//! }
//! }
//!
//! graph! {
//! digraph MemoryEcho {
//! node[shape=box];
//!
//! get_input[label="Get Input", type=GetInput, start=true];
//! echo_and_exit[label="Echo Recorded\nInput and Exit", type=EchoAndExit];
//! record[label="Record and Loop", type=Record, branch=matcher];
//!
//! get_input -> record;
//! record -> echo_and_exit [label=exit, value=exit];
//! record -> get_input;
//! }
//! }
//!
//! fn main() {
//! MemoryEcho::run(());
//! }
//! ```
pub use ;
pub use BranchTracker;
pub use DependencyCache;