Skip to main content

rill_core/traits/
mod.rs

1//! # Core Traits for Rill
2//!
3//! This module defines the fundamental traits that form the backbone
4//! of the Rill ecosystem.
5/// Algorithm trait and action contexts.
6pub mod algorithm;
7/// Bridge backend trait for duplex execution boundary.
8pub mod bridge;
9/// BufferView trait for backend-specific ring buffer access.
10pub mod buffer_view;
11mod error;
12/// MultichannelAlgorithm trait for multi-IO processing (N inputs, M outputs).
13pub mod multichannel_algorithm;
14/// Parameter types and IDs (`ParameterId`, `ParamValue`, `ParamType`, etc.).
15pub mod param;
16/// ParameterWrite trait — polymorphic control interface for DSP engines.
17pub mod parameter_write;
18/// Rack archetype — modular processing unit (Eurorack case).
19pub mod rack;
20// Re-export all public items
21pub use algorithm::*;
22pub use buffer_view::*;
23pub use error::*;
24pub use multichannel_algorithm::*;
25pub use param::*;
26pub use parameter_write::*;
27pub use rack::*;
28// ============================================================================
29// Common Type Aliases
30// ============================================================================
31/// Default block size for signal processing
32pub const DEFAULT_BLOCK_SIZE: usize = 64;
33/// Type alias for a mono signal block
34pub type MonoBlock<T, const BUF_SIZE: usize> = [T; BUF_SIZE];
35/// Type alias for a stereo signal block (left, right)
36pub type StereoBlock<T, const BUF_SIZE: usize> = [MonoBlock<T, BUF_SIZE>; 2];
37/// Type alias for a control signal value
38pub type ControlValue<T> = T;
39// ============================================================================
40// Prelude - Convenient imports for common use
41// ============================================================================
42/// Prelude module for convenient importing of common traits and types
43pub mod prelude {
44    // Re-export from parent modules
45    pub use super::{
46        // Core traits
47        BufferView,
48        Eurorack,
49        ParamMetadata,
50        ParamRange,
51        ParamType,
52        ParamValue,
53        ParameterError,
54        // Parameter handling
55        ParameterId,
56        ParameterResult,
57        ParameterWrite,
58        ProcessError,
59        // Error types
60        ProcessResult, // Constants
61        DEFAULT_BLOCK_SIZE,
62    };
63    // Re-export Transcendental from math module for convenience
64    pub use crate::math::Transcendental;
65}
66// ============================================================================
67// Common Helper Traits
68// ============================================================================
69/// Trait for types that can be converted to/from `ParamValue`
70pub trait IntoParamValue: Sized {
71    /// Convert this value into a `ParamValue`
72    fn into_param_value(self) -> ParamValue;
73    /// Try to convert a `ParamValue` back into this type
74    fn from_param_value(value: ParamValue) -> Option<Self>;
75}
76impl IntoParamValue for f32 {
77    fn into_param_value(self) -> ParamValue {
78        ParamValue::Float(self)
79    }
80    fn from_param_value(value: ParamValue) -> Option<Self> {
81        value.as_f32()
82    }
83}
84impl IntoParamValue for i32 {
85    fn into_param_value(self) -> ParamValue {
86        ParamValue::Int(self)
87    }
88    fn from_param_value(value: ParamValue) -> Option<Self> {
89        value.as_i32()
90    }
91}
92impl IntoParamValue for bool {
93    fn into_param_value(self) -> ParamValue {
94        ParamValue::Bool(self)
95    }
96    fn from_param_value(value: ParamValue) -> Option<Self> {
97        value.as_bool()
98    }
99}
100impl IntoParamValue for String {
101    fn into_param_value(self) -> ParamValue {
102        ParamValue::String(self)
103    }
104    fn from_param_value(value: ParamValue) -> Option<Self> {
105        match value {
106            ParamValue::String(s) => Some(s),
107            ParamValue::Choice(s) => Some(s),
108            _ => None,
109        }
110    }
111}
112// ============================================================================
113// Blanket Implementations
114// ============================================================================
115/// Helper trait for downcasting to concrete types
116pub trait AsAny: 'static {
117    /// Convert to `&dyn std::any::Any`
118    fn as_any(&self) -> &dyn std::any::Any;
119    /// Convert to `&mut dyn std::any::Any`
120    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
121}
122impl<T: 'static> AsAny for T {
123    fn as_any(&self) -> &dyn std::any::Any {
124        self
125    }
126    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
127        self
128    }
129}
130// ============================================================================
131// Tests
132// ============================================================================
133#[cfg(test)]
134mod tests {
135    use super::prelude::*;
136    #[test]
137    fn test_param_value_conversions() {
138        let f = ParamValue::Float(42.0);
139        assert_eq!(f.as_f32(), Some(42.0));
140        assert_eq!(f.as_i32(), Some(42));
141        assert_eq!(f.as_bool(), Some(true));
142        let i = ParamValue::Int(0);
143        assert_eq!(i.as_f32(), Some(0.0));
144        assert_eq!(i.as_i32(), Some(0));
145        assert_eq!(i.as_bool(), Some(false));
146        let b = ParamValue::Bool(true);
147        assert_eq!(b.as_f32(), Some(1.0));
148        assert_eq!(b.as_i32(), Some(1));
149        assert_eq!(b.as_bool(), Some(true));
150    }
151    #[test]
152    fn test_parameter_id_validation() {
153        assert!(ParameterId::new("gain").is_ok());
154        assert!(ParameterId::new("cutoff_freq").is_ok());
155        assert!(ParameterId::new("delay_time_2").is_ok());
156        assert!(ParameterId::new("").is_err());
157        assert!(ParameterId::new("1gain").is_err());
158        assert!(ParameterId::new("_gain").is_err());
159        assert!(ParameterId::new("gain.value").is_ok());
160    }
161    #[test]
162    fn test_param_range() {
163        let range = ParamRange::new().with_min(0.0).with_max(1.0).with_step(0.1);
164        assert!(range.contains(0.5));
165        assert!(!range.contains(1.5));
166        assert_eq!(range.clamp(1.5), 1.0);
167        assert_eq!(range.clamp(-0.5), 0.0);
168    }
169    #[test]
170    fn test_default_block_size() {
171        assert_eq!(DEFAULT_BLOCK_SIZE, 64);
172    }
173}