Starting to support arrays and tuples for inout
This commit is contained in:
120
Cargo.lock
generated
120
Cargo.lock
generated
@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "example"
|
||||
version = "0.1.0"
|
||||
@ -10,11 +16,86 @@ dependencies = [
|
||||
"oxydsp-flowgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxydsp-dsp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num",
|
||||
"oxydsp-flowgraph",
|
||||
"rustfft",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -41,6 +122,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primal-check"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
@ -59,6 +149,26 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustfft"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"primal-check",
|
||||
"strength_reduce",
|
||||
"transpose",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strength_reduce"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
@ -70,6 +180,16 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "transpose"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"strength_reduce",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
use std::{fmt::Display, fs::File, io::Write};
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
use oxydsp_dsp::blocks::{math::basic::Adder, utilities::iter::IterSource};
|
||||
use oxydsp_flowgraph::{
|
||||
BlockIO,
|
||||
block::{Block, BlockResult},
|
||||
edge::{In, PopIterable},
|
||||
flowgraph,
|
||||
graph::FlowGraph,
|
||||
};
|
||||
use oxydsp_dsp::blocks::math::basic::Adder;
|
||||
use oxydsp_dsp::blocks::utilities::iter::IterSource;
|
||||
use oxydsp_flowgraph::BlockIO;
|
||||
use oxydsp_flowgraph::block::Block;
|
||||
use oxydsp_flowgraph::block::BlockResult;
|
||||
use oxydsp_flowgraph::edge::In;
|
||||
use oxydsp_flowgraph::edge::PopIter;
|
||||
use oxydsp_flowgraph::edge::PopIterable;
|
||||
use oxydsp_flowgraph::flowgraph;
|
||||
use oxydsp_flowgraph::graph::FlowGraph;
|
||||
use oxydsp_flowgraph::stream::StreamReader;
|
||||
|
||||
#[derive(BlockIO)]
|
||||
//#[derive(BlockIO)]
|
||||
pub struct Printer<T: 'static>
|
||||
{
|
||||
#[input]
|
||||
input: In<T>,
|
||||
//#[input]
|
||||
input: [In<T>; 3],
|
||||
|
||||
n: usize,
|
||||
}
|
||||
@ -22,7 +27,8 @@ impl<T: 'static> Printer<T>
|
||||
{
|
||||
pub fn new(input: In<T>) -> Self
|
||||
{
|
||||
Self { input, n: 0 }
|
||||
todo!()
|
||||
//Self { input, n: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +38,12 @@ where
|
||||
{
|
||||
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
|
||||
{
|
||||
for x in self.input.pop_iter()
|
||||
let mut k: Vec<_> = self.input.iter_mut().map(|x| x.read()).collect();
|
||||
|
||||
k[0].pop();
|
||||
k[1].next();
|
||||
|
||||
for x in self.input[0].pop_iter()
|
||||
{
|
||||
if self.n.is_multiple_of(2usize.pow(20))
|
||||
{
|
||||
|
||||
@ -4,4 +4,6 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
num = "0.4.3"
|
||||
oxydsp-flowgraph = {path = "../oxydsp-flowgraph/"}
|
||||
rustfft = "6.4.1"
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod math;
|
||||
pub mod synthesis;
|
||||
pub mod utilities;
|
||||
|
||||
81
oxydsp-dsp/src/blocks/synthesis.rs
Normal file
81
oxydsp-dsp/src/blocks/synthesis.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use crate::units::DigitalFrequency;
|
||||
use num::Complex;
|
||||
use num::Float;
|
||||
use oxydsp_flowgraph::BlockIO;
|
||||
use oxydsp_flowgraph::block::Block;
|
||||
use oxydsp_flowgraph::block::BlockResult;
|
||||
use oxydsp_flowgraph::edge::In;
|
||||
use oxydsp_flowgraph::edge::Out;
|
||||
use oxydsp_flowgraph::edge::PopIterable;
|
||||
use oxydsp_flowgraph::edge::stream;
|
||||
|
||||
#[derive(BlockIO)]
|
||||
pub struct OscillatorSource<T: Float + From<f32> + 'static>
|
||||
{
|
||||
nco: crate::synthesis::oscillator::Nco<T>,
|
||||
|
||||
#[output]
|
||||
output: Out<Complex<T>>,
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32> + 'static> OscillatorSource<T>
|
||||
{
|
||||
pub fn new(nco: crate::synthesis::oscillator::Nco<T>) -> (Self, In<Complex<T>>)
|
||||
{
|
||||
let (output, signal) = stream();
|
||||
(Self { nco, output }, signal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32> + 'static> Block for OscillatorSource<T>
|
||||
{
|
||||
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
|
||||
{
|
||||
self.output.push_iter(&mut self.nco);
|
||||
BlockResult::Ok
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(BlockIO)]
|
||||
pub struct Nco<T: Float + From<f32> + 'static>
|
||||
{
|
||||
nco: crate::synthesis::oscillator::Nco<T>,
|
||||
|
||||
#[input]
|
||||
frequency: In<DigitalFrequency>,
|
||||
|
||||
#[output]
|
||||
output: Out<Complex<T>>,
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32> + 'static> Nco<T>
|
||||
{
|
||||
pub fn new(
|
||||
input: In<DigitalFrequency>,
|
||||
nco: crate::synthesis::oscillator::Nco<T>,
|
||||
) -> (Self, In<Complex<T>>)
|
||||
{
|
||||
let (output, signal) = stream();
|
||||
(
|
||||
Self {
|
||||
nco,
|
||||
frequency: input,
|
||||
output,
|
||||
},
|
||||
signal,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32> + 'static> Block for Nco<T>
|
||||
{
|
||||
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
|
||||
{
|
||||
self.output
|
||||
.push_iter(&mut self.frequency.pop_iter().map(|f| {
|
||||
self.nco.set_frequency(f);
|
||||
self.nco.next().unwrap()
|
||||
}));
|
||||
BlockResult::Ok
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
pub mod adapters;
|
||||
pub mod iter;
|
||||
|
||||
1
oxydsp-dsp/src/blocks/utilities/adapters.rs
Normal file
1
oxydsp-dsp/src/blocks/utilities/adapters.rs
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -1 +1,10 @@
|
||||
use num::Float;
|
||||
|
||||
pub mod blocks;
|
||||
pub mod synthesis;
|
||||
pub mod units;
|
||||
|
||||
fn map<T: Float>(x: T, x_min: T, x_max: T, o_min: T, o_max: T) -> T
|
||||
{
|
||||
((x - x_min) / (x_max - x_min)) * (o_max - o_min) + o_min
|
||||
}
|
||||
|
||||
1
oxydsp-dsp/src/synthesis.rs
Normal file
1
oxydsp-dsp/src/synthesis.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod oscillator;
|
||||
91
oxydsp-dsp/src/synthesis/oscillator.rs
Normal file
91
oxydsp-dsp/src/synthesis/oscillator.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::f32::consts::PI;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use num::Complex;
|
||||
use num::Float;
|
||||
|
||||
use crate::map;
|
||||
use crate::units::DigitalFrequency;
|
||||
use crate::units::Phase;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Nco<T>
|
||||
{
|
||||
// Current phase angle of the oscillator
|
||||
phase: usize,
|
||||
|
||||
// "Phase derivative": How much to increase the phase per sample
|
||||
d_phase: usize,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Nco<T>
|
||||
{
|
||||
pub fn new(frequency: DigitalFrequency) -> Self
|
||||
{
|
||||
Self {
|
||||
phase: 0,
|
||||
d_phase: frequency.0,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_phase(frequency: DigitalFrequency, phase: Phase) -> Self
|
||||
{
|
||||
Self {
|
||||
phase: phase.0.0,
|
||||
d_phase: frequency.0,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_phase(&mut self, phase: Phase)
|
||||
{
|
||||
self.phase = phase.0.0;
|
||||
}
|
||||
|
||||
pub fn set_frequency(&mut self, frequency: DigitalFrequency)
|
||||
{
|
||||
self.d_phase = frequency.0;
|
||||
}
|
||||
|
||||
pub fn step(&mut self)
|
||||
{
|
||||
let _ = self.phase.overflowing_add(self.d_phase);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32>> Nco<T>
|
||||
{
|
||||
pub fn sample(&self) -> Complex<T>
|
||||
{
|
||||
let t = map(
|
||||
<T as From<f32>>::from(self.phase as f32),
|
||||
<T as From<f32>>::from(0.0f32),
|
||||
<T as From<f32>>::from(usize::MAX as f32),
|
||||
<T as From<f32>>::from(0.0f32),
|
||||
<T as From<f32>>::from(2. * PI),
|
||||
);
|
||||
Complex::new(t.cos(), t.sin())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + From<f32>> Iterator for Nco<T>
|
||||
{
|
||||
type Item = Complex<T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item>
|
||||
{
|
||||
let s = self.sample();
|
||||
self.step();
|
||||
Some(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<DigitalFrequency> for Nco<T>
|
||||
{
|
||||
fn from(value: DigitalFrequency) -> Self
|
||||
{
|
||||
Nco::new(value)
|
||||
}
|
||||
}
|
||||
38
oxydsp-dsp/src/units.rs
Normal file
38
oxydsp-dsp/src/units.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use std::f64::consts::PI;
|
||||
|
||||
use crate::map;
|
||||
|
||||
// Represents digital frequency
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||
pub struct DigitalFrequency(pub usize);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||
pub struct Phase(pub DigitalFrequency);
|
||||
|
||||
impl DigitalFrequency
|
||||
{
|
||||
pub fn from_rad(radians_per_sample: f64) -> Self
|
||||
{
|
||||
// Frequnecy wraps arround : Going at 2 pi radians per second
|
||||
// Is like not oscillating at all
|
||||
let f = radians_per_sample.rem_euclid(radians_per_sample);
|
||||
|
||||
// Then we map the [0, 2*PI] range into the 0 to usize range
|
||||
DigitalFrequency(map(f, 0., 2. * PI, 0., usize::MAX as f64).floor() as usize)
|
||||
}
|
||||
|
||||
pub fn from_time_frequency(hertz: f64, sample_rate: f64) -> Self
|
||||
{
|
||||
Self::from_rad(map(hertz, 0., sample_rate, 0., 2. * PI))
|
||||
}
|
||||
|
||||
pub fn as_rad(&self) -> f64
|
||||
{
|
||||
map(self.0 as f64, 0., usize::MAX as f64, 0., 2. * PI)
|
||||
}
|
||||
|
||||
pub fn as_time_frequency(&self, sample_rate: f64) -> f64
|
||||
{
|
||||
map(self.0 as f64, 0., usize::MAX as f64, 0., sample_rate)
|
||||
}
|
||||
}
|
||||
279
oxydsp-flowgraph/oxydsp-flowgraph-macros/src/block_io.rs
Normal file
279
oxydsp-flowgraph/oxydsp-flowgraph-macros/src/block_io.rs
Normal file
@ -0,0 +1,279 @@
|
||||
use proc_macro::TokenStream;
|
||||
use zyn::ToTokens;
|
||||
use zyn::ext::AttrExt;
|
||||
use zyn::ext::FieldsExt;
|
||||
use zyn::syn::Attribute;
|
||||
use zyn::syn::Index;
|
||||
use zyn::syn::spanned::Spanned;
|
||||
|
||||
pub enum BlockIOPort
|
||||
{
|
||||
Field(TokenStream),
|
||||
Array(TokenStream, TokenStream),
|
||||
}
|
||||
|
||||
pub struct BlockIOPorts
|
||||
{
|
||||
inputs: Vec<BlockIOPort>,
|
||||
outputs: Vec<BlockIOPort>,
|
||||
}
|
||||
|
||||
pub fn parse_ports(fields: zyn::syn::Fields, attribute: &str) -> Vec<BlockIOPort>
|
||||
{
|
||||
let mut ports = vec![];
|
||||
let fields = fields.as_named().unwrap();
|
||||
|
||||
for field in fields.named.iter()
|
||||
{
|
||||
if field.attrs.iter().any(|attr| attr.is(attribute))
|
||||
{
|
||||
ports.append(&mut parse_port(field.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
ports.iter().for_each(|x| match x
|
||||
{
|
||||
BlockIOPort::Field(token_stream) => println!("field: {}", token_stream),
|
||||
BlockIOPort::Array(token_stream, token_stream1) =>
|
||||
{
|
||||
println!("array: {} [{}]", token_stream, token_stream1)
|
||||
}
|
||||
});
|
||||
|
||||
ports
|
||||
}
|
||||
|
||||
pub fn parse_port(field: zyn::syn::Field) -> Vec<BlockIOPort>
|
||||
{
|
||||
match field.ty
|
||||
{
|
||||
zyn::syn::Type::Path(type_path) =>
|
||||
{
|
||||
println!("{:?}", type_path.path);
|
||||
assert!(type_path.path.is_ident("In") || type_path.path.is_ident("Out"));
|
||||
vec![BlockIOPort::Field(
|
||||
field.ident.unwrap().to_token_stream().into(),
|
||||
)]
|
||||
}
|
||||
zyn::syn::Type::Tuple(type_tuple) =>
|
||||
{
|
||||
let mut output = vec![];
|
||||
for (i, _) in type_tuple.elems.iter().enumerate()
|
||||
{
|
||||
output.push(BlockIOPort::Field(
|
||||
zyn::zyn!({{field.ident.clone().unwrap()}}.{{ Index::from(i) }})
|
||||
.to_token_stream()
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
output
|
||||
}
|
||||
zyn::syn::Type::Array(type_array) =>
|
||||
{
|
||||
let b = BlockIOPort::Array(
|
||||
field.ident.clone().unwrap().to_token_stream().into(),
|
||||
type_array.len.to_token_stream().into(),
|
||||
);
|
||||
vec![b]
|
||||
}
|
||||
_ => panic!("Unsupported port type."),
|
||||
}
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn block_io_set_index(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn set_index(&self, block_index: usize)
|
||||
{
|
||||
use oxydsp_flowgraph::edge::BlockIOIndex;
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
self.{{field.1.ident}}.set_block_index(BlockIOIndex {block_index, port_index: {{ field.0 }} });
|
||||
}
|
||||
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
self.{{field.1.ident}}.set_block_index(BlockIOIndex {block_index, port_index: {{ field.0 }} });
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn block_io_get_successors(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn get_successors(&self) -> Vec<oxydsp_flowgraph::edge::BlockIOIndex>
|
||||
{
|
||||
let mut output = vec![];
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
if let Some(block_index) = self.{{ field.1.ident }}.get_consumer_block()
|
||||
{
|
||||
output.push(block_index);
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn block_io_get_meta(ident: zyn::syn::Ident, fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn get_block_name(&self) -> &'static str
|
||||
{
|
||||
return {{ ident.to_string() }};
|
||||
}
|
||||
|
||||
fn get_input_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
output.push({{ field.1.ident.clone().unwrap().to_string() }});
|
||||
}
|
||||
return output;
|
||||
}
|
||||
fn get_output_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
output.push({{ field.1.ident.clone().unwrap().to_string() }});
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
fn get_output_type_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
output.push(self.{{ field.1.ident.clone() }}.get_type_name());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn block_io_counts(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
let input_count = fields
|
||||
.iter()
|
||||
.filter(|x| x.attrs.iter().any(|x| x.is("input")))
|
||||
.count();
|
||||
let output_count = fields
|
||||
.iter()
|
||||
.filter(|x| x.attrs.iter().any(|x| x.is("output")))
|
||||
.count();
|
||||
zyn::zyn!(
|
||||
fn input_count(&self) -> usize
|
||||
{
|
||||
return { { input_count } };
|
||||
}
|
||||
|
||||
fn output_count(&self) -> usize
|
||||
{
|
||||
return { { output_count } };
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element(debug = "pretty")]
|
||||
pub fn block_io_set_streams(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
zyn::zyn!(
|
||||
#[allow(unreachable_code)]
|
||||
fn set_anonymous_out_stream(
|
||||
&mut self,
|
||||
output_index: usize,
|
||||
producer: oxydsp_flowgraph::edge::AnonymousStreamProducer,
|
||||
)
|
||||
{
|
||||
match output_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} => self.{{field.1.ident}}.set_anonymous_stream(producer),
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn set_anonymous_in_stream(&mut self, input_index: usize, consumer: oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
{
|
||||
match input_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} => self.{{field.1.ident}}.set_anonymous_stream(consumer),
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn block_io_create_stream(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
zyn::zyn!(
|
||||
#[allow(unreachable_code)]
|
||||
fn create_anonymous_stream_for(
|
||||
&mut self,
|
||||
output_index: usize,
|
||||
capacity: usize
|
||||
) -> (oxydsp_flowgraph::edge::AnonymousStreamProducer, oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
{
|
||||
let (tx, rx): (oxydsp_flowgraph::edge::AnonymousStreamProducer, oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
= match output_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} =>
|
||||
{
|
||||
let (tx, rx) = oxydsp_flowgraph::stream::bounded_queue::<@out_inner_type(ty = field.1.ty.clone())>(capacity);
|
||||
(tx.into(), rx.into())
|
||||
},
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
|
||||
(tx, rx)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
pub fn out_inner_type(ty: zyn::syn::Type) -> zyn::TokenStream
|
||||
{
|
||||
let out_ty = match ty
|
||||
{
|
||||
zyn::syn::Type::Path(type_path) => match &type_path.path.segments.last().unwrap().arguments
|
||||
{
|
||||
zyn::syn::PathArguments::AngleBracketed(args) => match args.args.first().unwrap()
|
||||
{
|
||||
zyn::syn::GenericArgument::Type(x) => Some(x.clone().to_token_stream()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if out_ty.is_none()
|
||||
{
|
||||
bail!("Output type must be a Out<T> type."; span = ty.span());
|
||||
}
|
||||
|
||||
out_ty.unwrap()
|
||||
}
|
||||
@ -8,6 +8,9 @@ use zyn::syn::Index;
|
||||
use zyn::syn::Lit;
|
||||
use zyn::syn::spanned::Spanned;
|
||||
|
||||
mod block_io;
|
||||
use crate::block_io::*;
|
||||
|
||||
#[zyn::derive("BlockIO", attributes(input, output), debug = "pretty")]
|
||||
pub fn block_io(
|
||||
#[zyn(input)] ident: zyn::Extract<zyn::syn::Ident>,
|
||||
@ -15,6 +18,7 @@ pub fn block_io(
|
||||
#[zyn(input)] fields: zyn::Fields,
|
||||
) -> zyn::TokenStream
|
||||
{
|
||||
//parse_ports(fields.clone(), "input");
|
||||
let ident = ident.inner();
|
||||
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
|
||||
zyn::zyn!(
|
||||
@ -31,204 +35,6 @@ pub fn block_io(
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn block_io_set_index(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn set_index(&self, block_index: usize)
|
||||
{
|
||||
use oxydsp_flowgraph::edge::BlockIOIndex;
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
self.{{field.1.ident}}.set_block_index(BlockIOIndex {block_index, port_index: {{ field.0 }} });
|
||||
}
|
||||
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
self.{{field.1.ident}}.set_block_index(BlockIOIndex {block_index, port_index: {{ field.0 }} });
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn block_io_get_successors(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn get_successors(&self) -> Vec<oxydsp_flowgraph::edge::BlockIOIndex>
|
||||
{
|
||||
let mut output = vec![];
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
if let Some(block_index) = self.{{ field.1.ident }}.get_consumer_block()
|
||||
{
|
||||
output.push(block_index);
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn block_io_get_meta(ident: zyn::syn::Ident, fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
zyn::zyn!(
|
||||
fn get_block_name(&self) -> &'static str
|
||||
{
|
||||
return {{ ident.to_string() }};
|
||||
}
|
||||
|
||||
fn get_input_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
output.push({{ field.1.ident.clone().unwrap().to_string() }});
|
||||
}
|
||||
return output;
|
||||
}
|
||||
fn get_output_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
output.push({{ field.1.ident.clone().unwrap().to_string() }});
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
fn get_output_type_names(&self) -> Vec<&'static str>
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
output.push(self.{{ field.1.ident.clone() }}.get_type_name());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn block_io_counts(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
let fields = fields.as_named().unwrap().named.clone();
|
||||
let input_count = fields
|
||||
.iter()
|
||||
.filter(|x| x.attrs.iter().any(|x| x.is("input")))
|
||||
.count();
|
||||
let output_count = fields
|
||||
.iter()
|
||||
.filter(|x| x.attrs.iter().any(|x| x.is("output")))
|
||||
.count();
|
||||
zyn::zyn!(
|
||||
fn input_count(&self) -> usize
|
||||
{
|
||||
return { { input_count } };
|
||||
}
|
||||
|
||||
fn output_count(&self) -> usize
|
||||
{
|
||||
return { { output_count } };
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element(debug = "pretty")]
|
||||
fn block_io_set_streams(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
zyn::zyn!(
|
||||
#[allow(unreachable_code)]
|
||||
fn set_anonymous_out_stream(
|
||||
&mut self,
|
||||
output_index: usize,
|
||||
producer: oxydsp_flowgraph::edge::AnonymousStreamProducer,
|
||||
)
|
||||
{
|
||||
match output_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} => self.{{field.1.ident}}.set_anonymous_stream(producer),
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn set_anonymous_in_stream(&mut self, input_index: usize, consumer: oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
{
|
||||
match input_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("input"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} => self.{{field.1.ident}}.set_anonymous_stream(consumer),
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn block_io_create_stream(fields: zyn::syn::Fields) -> zyn::TokenStream
|
||||
{
|
||||
zyn::zyn!(
|
||||
#[allow(unreachable_code)]
|
||||
fn create_anonymous_stream_for(
|
||||
&mut self,
|
||||
output_index: usize,
|
||||
capacity: usize
|
||||
) -> (oxydsp_flowgraph::edge::AnonymousStreamProducer, oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
{
|
||||
let (tx, rx): (oxydsp_flowgraph::edge::AnonymousStreamProducer, oxydsp_flowgraph::edge::AnonymousStreamConsumer)
|
||||
= match output_index
|
||||
{
|
||||
@for (field in fields.iter().filter(|x| x.attrs.iter().any(|x| x.is("output"))).enumerate())
|
||||
{
|
||||
{{ field.0 }} =>
|
||||
{
|
||||
let (tx, rx) = oxydsp_flowgraph::stream::bounded_queue::<@out_inner_type(ty = field.1.ty.clone())>(capacity);
|
||||
(tx.into(), rx.into())
|
||||
},
|
||||
}
|
||||
_ => panic!("output_index out of bounds.")
|
||||
};
|
||||
|
||||
(tx, rx)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[zyn::element]
|
||||
fn out_inner_type(ty: zyn::syn::Type) -> zyn::TokenStream
|
||||
{
|
||||
let out_ty = match ty
|
||||
{
|
||||
zyn::syn::Type::Path(type_path) => match &type_path.path.segments.last().unwrap().arguments
|
||||
{
|
||||
zyn::syn::PathArguments::AngleBracketed(args) => match args.args.first().unwrap()
|
||||
{
|
||||
zyn::syn::GenericArgument::Type(x) => Some(x.clone().to_token_stream()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if out_ty.is_none()
|
||||
{
|
||||
bail!("Output type must be a Out<T> type."; span = ty.span());
|
||||
}
|
||||
|
||||
out_ty.unwrap()
|
||||
}
|
||||
|
||||
// Sync block
|
||||
|
||||
#[zyn::attribute]
|
||||
|
||||
Reference in New Issue
Block a user