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
//! Combinators.
//!
//! # How to read this documentation
//!
//! If you're reading the source code, you can go to each module listed in the [Categories](#categories) section to see
//! the combinators' documentation and implementation.
//!
//! If you're viewing the generated documentation in the browser, you should go to the following pages to see the
//! documentation.
//!
//! - Combinators implemented directly on an interface (All combinators other than N-to-1 combinators)
//! - [`I<H, D>`#implementations]
//! - Combinators implemented on tuples or arrays (N-to-1 combinators)
//! - [`JoinExt`#foreign-impls]
//! - [`JoinValidExt`#foreign-impls]
//! - [`JoinVrExt`#foreign-impls]
//! - [`ZipAnyExt`#foreign-impls]
//! - [`ZipAnyValidExt`#foreign-impls]
//! - [`MergeExt`#foreign-impls]
//! - [`MuxExt`#foreign-impls]
//!
//! # Categories
//!
//! The combinators can be organized into the following categories.
//!
//! - Mapping
//! - [`filter_map`]
//! - [`filter`]
//! - [`map`]
//! - [`map_resolver`]
//! - [`flatten`]
//! - 1-to-N
//! - Distribute to all
//! - [`fork`]
//! - [`unzip`]
//! - Distribute to some
//! - [`fork_some`]
//! - [`unzip_some`]
//! - Distribute to one
//! - [`branch`]
//! - N-to-1
//! - Keep all
//! - [`join`]
//! - Keep some
//! - [`zip_any`]
//! - Choose one
//! - [`merge`]
//! - [`mux`]
//! - Register
//! - [`reg`]
//! - [`fifo`]
//! - Source/sink
//! - [`sink`]
//! - [`source`]
//! - FSM
//! - [`fsm_map`]
//! - [`fsm_ingress`]
//! - [`fsm_egress`]
//! - Conversion
//! - [`convert`]
//!
//! # Naming conventions
//!
//! The combinators have a main name, and can have various prefixes and suffixes clarifying their behavior.
//!
//! - Combinators that may change the payload/resolver (Mapping, Source/sink, FSM combinators)
//! - No additional words: Other than what the combinator itself does, does not change the validity of the payload
//! nor the readiness of the resolver.
//! - Suffix `drop`: If the egress hazard ready condition (`EH::ready`) is false, the egress payload becomes `None`.
//! - Suffix `block`: If the egress hazard ready condition (`EH::ready`) is false, send an additional "not ready"
//! signal to the ingress resolver.
//! - Combinators with an internal state (Register, FSM combinators)
//! - Prefix `transparent`: Outputs the internal state to the ingress resolver.
//! - Conversion combinators
//! - Start with `into`: The combinator doesn't change the behavior in a meaningful way. You can just use it to get
//! the type you want.
//! - Start with other words (`discard`/`always`/`drop`/`block`): The combinator does change the behavior. Refer to
//! each combinator's documentation for more information.
//! - Combinators with a closure argument
//! - Suffix `with_p`/`with_r`: The closure takes an additional payload/resolver parameter.
//! - (For `I<VrH<P, R>, _>`) Suffix `inner`: The closure takes the inner value `R` of the resolver instead of the
//! whole `Ready<R>`.
//!
//! # Notes on dropping combinators
//!
//! If a combinator returns a [`Dep::Demanding`] interface because of the semantics of the combinator, it has to have a
//! dropping behavior to force the required condition for [`Dep::Demanding`]. (If the payload is `Some`,
//! `Hazard::ready(p, r)` is true.) Note that for `I<ValidH<P, R>, _>`, this is unnecessary as `ValidH::ready` is always
//! true.
//!
//! For the combinators implemented on a generic hazard interface `I<H, _>` that allows the caller to choose the egress
//! hazard `EH`, the returned interface is forced to be [`Dep::Demanding`], making them have a dropping behavior.
//! This is because the combinator first has to check the ingress transfer condition
//! (`ip.is_some_and(|p| H::ready(p, ir))`). Otherwise, checking `H::ready` will never be done as the hazard type and
//! thus the ready condition is changed to `EH::ready`. This makes the egress payload depend on the ingress resolver,
//! and in turn the egress resolver.
// Note that this has to be above `mod`s since it uses textual scope.
/// Adopted from https://veykril.github.io/tlborm/decl-macros/patterns/repetition-replacement.html.
macro_rules! replace {
($_t:tt, $($sub:tt)+) => {
$($sub)+
};
}
// Mapping
pub mod filter;
pub mod filter_map;
pub mod flatten;
pub mod map;
pub mod map_resolver;
// 1-to-N
pub mod branch;
pub mod fork;
pub mod fork_some;
pub mod unzip;
pub mod unzip_some;
// N-to-1
pub mod join;
pub mod merge;
pub mod mux;
pub mod zip_any;
// Register
pub mod fifo;
pub mod reg;
// Source/sink
pub mod sink;
pub mod source;
// FSM
pub mod fsm_egress;
pub mod fsm_ingress;
pub mod fsm_map;
// Conversion
pub mod convert;
// Other
pub mod generator;
pub use fifo::*;
pub use join::*;
pub use merge::*;
pub use mux::*;
pub use zip_any::*;
use super::hazard::*;
use super::valid::*;
use crate::prelude::*;
use crate::std::*;