futuresdr/blocks/
finite_source.rs

1use crate::prelude::*;
2
3/// Repeatedly apply a function to generate samples, using [Option] values to allow termination.
4#[derive(Block)]
5pub struct FiniteSource<F, A, O = DefaultCpuWriter<A>>
6where
7    F: FnMut() -> Option<A> + Send + 'static,
8    A: Send + 'static,
9    O: CpuBufferWriter<Item = A>,
10{
11    #[output]
12    output: O,
13    f: F,
14}
15
16impl<F, A, O> FiniteSource<F, A, O>
17where
18    F: FnMut() -> Option<A> + Send + 'static,
19    A: Send + 'static,
20    O: CpuBufferWriter<Item = A>,
21{
22    /// Create FiniteSource block
23    pub fn new(f: F) -> Self {
24        Self {
25            output: O::default(),
26            f,
27        }
28    }
29}
30
31#[doc(hidden)]
32impl<F, A, O> Kernel for FiniteSource<F, A, O>
33where
34    F: FnMut() -> Option<A> + Send + 'static,
35    A: Send + 'static,
36    O: CpuBufferWriter<Item = A>,
37{
38    async fn work(
39        &mut self,
40        io: &mut WorkIo,
41        _mio: &mut MessageOutputs,
42        _meta: &mut BlockMeta,
43    ) -> Result<()> {
44        let o = self.output.slice();
45        let o_len = o.len();
46
47        for (i, v) in o.iter_mut().enumerate() {
48            match (self.f)() {
49                Some(x) => {
50                    *v = x;
51                }
52                _ => {
53                    self.output.produce(i);
54                    io.finished = true;
55                    return Ok(());
56                }
57            }
58        }
59
60        self.output.produce(o_len);
61        Ok(())
62    }
63}