Skip to main content

async_flow/model/
outputs.rs

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