fluxion_stream/
types.rs

1// Copyright 2025 Umberto Gotti <umberto.gotti@umbertogotti.dev>
2// Licensed under the Apache License, Version 2.0
3// http://www.apache.org/licenses/LICENSE-2.0
4
5//! Common types and type aliases used throughout the fluxion-stream crate.
6//!
7//! This module centralizes shared types to reduce duplication and improve maintainability.
8
9use fluxion_core::Ordered;
10use std::fmt::Debug;
11
12/// Represents a value paired with its previous value in the stream.
13///
14/// Used by [`CombineWithPreviousExt`](crate::CombineWithPreviousExt) to provide
15/// both current and previous values.
16#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
17pub struct WithPrevious<T> {
18    /// The previous value in the stream, if any
19    pub previous: Option<T>,
20    /// The current value in the stream
21    pub current: T,
22}
23
24impl<T> WithPrevious<T> {
25    /// Creates a new WithPrevious with the given previous and current values.
26    pub fn new(previous: Option<T>, current: T) -> Self {
27        Self { previous, current }
28    }
29
30    /// Returns true if there is a previous value.
31    pub fn has_previous(&self) -> bool {
32        self.previous.is_some()
33    }
34
35    /// Returns a tuple of references to (previous, current) if previous exists.
36    pub fn as_pair(&self) -> Option<(&T, &T)> {
37        self.previous.as_ref().map(|prev| (prev, &self.current))
38    }
39}
40
41impl<T: Ordered> Ordered for WithPrevious<T> {
42    type Inner = T::Inner;
43
44    fn order(&self) -> u64 {
45        self.current.order()
46    }
47
48    fn get(&self) -> &Self::Inner {
49        self.current.get()
50    }
51
52    fn with_order(value: Self::Inner, order: u64) -> Self {
53        Self {
54            previous: None,
55            current: T::with_order(value, order),
56        }
57    }
58
59    fn into_inner(self) -> Self::Inner {
60        self.current.into_inner()
61    }
62}
63
64/// State container holding the latest values from multiple combined streams.
65///
66/// Used by operators that combine multiple streams such as [`combine_latest`](crate::CombineLatestExt::combine_latest),
67/// [`with_latest_from`](crate::WithLatestFromExt::with_latest_from), and
68/// [`emit_when`](crate::EmitWhenExt::emit_when).
69///
70/// # Examples
71///
72/// ```
73/// use fluxion_stream::CombinedState;
74///
75/// let state = CombinedState::new(vec![1, 2, 3]);
76/// assert_eq!(state.values().len(), 3);
77/// assert_eq!(state.values()[0], 1);
78/// ```
79#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
80pub struct CombinedState<V>
81where
82    V: Clone + Debug + Ord,
83{
84    state: Vec<V>,
85}
86
87impl<V> CombinedState<V>
88where
89    V: Clone + Debug + Ord,
90{
91    /// Creates a new CombinedState with the given vector of values.
92    pub fn new(state: Vec<V>) -> Self {
93        Self { state }
94    }
95
96    /// Returns a reference to the internal values vector.
97    pub fn values(&self) -> &Vec<V> {
98        &self.state
99    }
100
101    /// Returns the number of streams in the combined state.
102    pub fn len(&self) -> usize {
103        self.state.len()
104    }
105
106    /// Returns true if there are no streams in the combined state.
107    pub fn is_empty(&self) -> bool {
108        self.state.is_empty()
109    }
110}
111
112impl<V> Ordered for CombinedState<V>
113where
114    V: Clone + Debug + Ord,
115{
116    type Inner = Self;
117
118    fn order(&self) -> u64 {
119        // CombinedState doesn't have its own order - it's always wrapped by an Ordered type
120        // This should never be called directly
121        0
122    }
123
124    fn get(&self) -> &Self::Inner {
125        self
126    }
127
128    fn with_order(value: Self::Inner, _order: u64) -> Self {
129        value
130    }
131
132    fn into_inner(self) -> Self::Inner {
133        self
134    }
135}
136
137/// Type alias for the common trait bounds used for ordered stream items.
138///
139/// This trait requires that types are:
140/// - `Ordered`: Have temporal ordering
141/// - `Clone`: Can be duplicated
142/// - `Debug`: Can be formatted for debugging
143/// - `Ord`: Have total ordering
144/// - `Send + Sync`: Can be safely transferred between threads
145/// - `Unpin`: Can be moved after being pinned
146/// - `'static`: Contains no non-static references
147///
148/// # Usage
149///
150/// Instead of writing:
151/// ```
152/// # use fluxion_stream::OrderedStreamItem;
153/// # use fluxion_core::Ordered;
154/// # use std::fmt::Debug;
155/// fn process_stream<T>()
156/// where
157///     T: Ordered + Clone + Debug + Ord + Send + Sync + Unpin + 'static
158/// # {}
159/// ```
160///
161/// You can write:
162/// ```
163/// # use fluxion_stream::OrderedStreamItem;
164/// fn process_stream<T>()
165/// where
166///     T: OrderedStreamItem
167/// # {}
168/// ```
169pub trait OrderedStreamItem: Ordered + Clone + Debug + Ord + Send + Sync + Unpin + 'static {}
170
171// Blanket implementation for all types that satisfy the bounds
172impl<T> OrderedStreamItem for T where
173    T: Ordered + Clone + Debug + Ord + Send + Sync + Unpin + 'static
174{
175}
176
177/// Type alias for the common trait bounds used for the inner values of ordered stream items.
178///
179/// This trait requires that inner types are:
180/// - `Clone`: Can be duplicated
181/// - `Debug`: Can be formatted for debugging
182/// - `Ord`: Have total ordering
183/// - `Send + Sync`: Can be safely transferred between threads
184/// - `'static`: Contains no non-static references
185///
186/// # Usage
187///
188/// Instead of writing:
189/// ```
190/// # use std::fmt::Debug;
191/// fn process_inner<T>()
192/// where
193///     T: Clone + Debug + Ord + Send + Sync + 'static
194/// # {}
195/// ```
196///
197/// You can write:
198/// ```
199/// # use fluxion_stream::OrderedInner;
200/// fn process_inner<T>()
201/// where
202///     T: OrderedInner
203/// # {}
204/// ```
205pub trait OrderedInner: Clone + Debug + Ord + Send + Sync + 'static {}
206
207// Blanket implementation for all types that satisfy the bounds
208impl<T> OrderedInner for T where T: Clone + Debug + Ord + Send + Sync + 'static {}
209
210/// Type alias for the common trait bounds used for ordered items that need to be
211/// unwrapped (without Unpin requirement).
212///
213/// Used in scenarios where the inner value needs to implement Ordered but doesn't
214/// need to be Unpin.
215pub trait OrderedInnerUnwrapped: Clone + Debug + Ord + Send + Sync + Unpin + 'static {}
216
217// Blanket implementation
218impl<T> OrderedInnerUnwrapped for T where T: Clone + Debug + Ord + Send + Sync + Unpin + 'static {}