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
//! # `jobflow`
//!
//! Do ordered jobs concurrently and easily. Designed to allow for arbitrary ordering of tasks
//! and sending the output of a task into the input of another.
//!
//! ## Jobs and Flows
//! A flow is composed of many jobs. Jobs are meant to be a form of atomic operations. The users
//! can create a job by giving it a name and assigning an [`Action`](actions::Action) to it. When using
//! [`Flow::create`] users can directly use any function of either signature `FnOnce() -> R` or `FnOnce(T) -> R`.
//! If using the former signature, attempting to set an input for this task will return an error.
//!
//!
//! ## Examples
//! ### No I/O
//! ```rust
//! use jobflow::Flow;
//! let mut flow = Flow::new();
//! flow.create("print something", || {
//! println!("Hello!")
//! });
//! flow.run().expect("failed to run");
//! ```
//!
//! ### Accepts an input, returns an output
//! ```rust
//! use jobflow::{Flow, FlowsInto};
//!
//! let mut flow = Flow::new();
//! let job = flow.input().flows_into(flow.create("square", |i: i32| { i * i }))
//! .unwrap().flows_into(flow.output())
//! .unwrap();
//! let output = flow.apply(10).unwrap();
//! assert_eq!(output, 100);
//! ```
//!
//! ### Multiple tasks can flow into a single task
//! Multiple tasks can be used an input into a single task using a funnel. As long as the input
//! of the action is something that implements `FromIterator<T>` and `IntoIterator<Item=T>`
//! ```rust
//! use jobflow::{Flow, FlowsInto};
//! let mut flow = Flow::new();
//! let funnel = flow.create("sum", |i: Vec<i32>| { i.iter().sum::<i32>()}).funnelled().unwrap();
//!
//! flow.create("a", || { 25_i32 }).flows_into(&funnel).unwrap();
//! flow.create("b", || { 50_i32 }).flows_into(&funnel).unwrap();
//! funnel.flows_into(flow.output()).expect("could set sum as output");
//! let sum = flow.get().expect("failed to get sum");
//! assert_eq!(sum, 75);
//! ```
//!
//! ### Task outputs can be disjointed to be consumed by multiple tasks
//!
//! Multiple tasks can take the output of a single task if the parts are disjoint from each other.
//! Unlike the [`Reusable`] type, the task's output doesn't need to be clonable. Currently, the output
//! of a disjointable task *must* be `Vec<T>`. Tasks that take the disjointed input can be any
//! `FromIterator<Item=T>` type.
//!
//! ```rust
//! use jobflow::{Flow, FlowsInto};
//! let mut flow = Flow::new();
//! let generator = flow.create("generator", || { (0..32).into_iter().collect::<Vec<i32>>() }).disjointed().unwrap();
//! let first_half = flow.create("1/2", |v: Vec<i32>| { assert_eq!(v.len(), 16)});
//! let second_half = flow.create("2/2", |v: Vec<i32>| { assert_eq!(v.len(), 16)});
//!
//! generator.gets(..16).flows_into(first_half).unwrap();
//! generator.gets(16..).flows_into(second_half).unwrap();
//!
//! flow.run().expect("failed to run flow");
//! ```
pub
pub use ;
pub use *;
pub use FlowThreadPool;