Skip to main content

async_flow/model/
outputs.rs

1// This is free and unencumbered software released into the public domain.
2
3use core::{
4    any::type_name,
5    marker::PhantomData,
6    ops::Bound,
7    sync::atomic::{AtomicIsize, Ordering},
8};
9
10pub type OutputId = isize;
11
12/// A one-shot output port of type `T`.
13///
14/// Note that `Output` doesn't implement `Copy`, whereas `Input` does.
15pub type Output<T> = Outputs<T, 1, 0>;
16
17/// An output port of type `T`.
18///
19/// Note that `Outputs` doesn't implement `Copy`, whereas `Inputs` does.
20#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
21pub struct Outputs<T, const MAX: isize = -1, const MIN: isize = 0>(OutputId, PhantomData<T>);
22
23impl<T, const MAX: isize, const MIN: isize> Default for Outputs<T, MAX, MIN> {
24    fn default() -> Self {
25        static COUNTER: AtomicIsize = AtomicIsize::new(1);
26        let id = COUNTER.fetch_add(1, Ordering::AcqRel);
27        Self(id, PhantomData)
28    }
29}
30
31impl<T, const MAX: isize, const MIN: isize> core::fmt::Debug for Outputs<T, MAX, MIN> {
32    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33        f.debug_tuple(&alloc::format!("Outputs<{}>", type_name::<T>()))
34            .field(&self.0)
35            .finish()
36    }
37}
38
39impl<T, const MAX: isize, const MIN: isize> Outputs<T, MAX, MIN> {
40    pub fn id(&self) -> OutputId {
41        self.0
42    }
43
44    /// Returns the cardinality of this connection.
45    pub fn cardinality() -> (Bound<usize>, Bound<usize>) {
46        assert!(MIN >= 0);
47        assert!(MAX >= -1);
48        use Bound::*;
49        match (MIN, MAX) {
50            (min, -1) => (Included(min as _), Unbounded),
51            (min, max) => (Included(min as _), Included(max as _)),
52        }
53    }
54}
55
56impl<T, const MAX: isize, const MIN: isize> Into<OutputId> for Outputs<T, MAX, MIN> {
57    fn into(self) -> OutputId {
58        self.0
59    }
60}