uni_core/primitives/
i16_buffer.rs

1// RUST CONCEPT: I16 buffer primitive for audio and DSP
2// Creates a new i16 buffer with specified size, initialized to zeros
3use crate::compat::Rc;
4use crate::interpreter::Interpreter;
5use crate::value::{RuntimeError, Value};
6
7#[cfg(not(target_os = "none"))]
8use std::cell::RefCell;
9#[cfg(target_os = "none")]
10use core::cell::RefCell;
11
12#[cfg(target_os = "none")]
13use alloc::vec;
14
15// RUST CONCEPT: Create i16 buffer primitive
16// Stack: ( size -- buffer )
17// Creates a new i16 buffer with 'size' samples, all initialized to 0
18pub fn i16_buffer_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
19    let size = interp.pop_integer()?;
20
21    // Create vector of zeros with the specified size
22    let buffer = vec![0i16; size];
23
24    // Wrap in Rc<RefCell<>> for shared mutable access
25    let buffer_value = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
26
27    interp.push(buffer_value);
28    Ok(())
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    fn setup_interpreter() -> Interpreter {
36        Interpreter::new()
37    }
38
39    #[test]
40    fn test_i16_buffer_create_empty() {
41        let mut interp = setup_interpreter();
42
43        // Create a buffer of size 0
44        interp.push(Value::Int32(0));
45        let result = i16_buffer_builtin(&mut interp);
46        assert!(result.is_ok());
47
48        let buffer = interp.pop().unwrap();
49        match buffer {
50            Value::I16Buffer(buf) => {
51                assert_eq!(buf.borrow().len(), 0);
52            }
53            _ => panic!("Expected I16Buffer"),
54        }
55    }
56
57    #[test]
58    fn test_i16_buffer_create_small() {
59        let mut interp = setup_interpreter();
60
61        // Create a buffer of size 10
62        interp.push(Value::Int32(10));
63        let result = i16_buffer_builtin(&mut interp);
64        assert!(result.is_ok());
65
66        let buffer = interp.pop().unwrap();
67        match buffer {
68            Value::I16Buffer(buf) => {
69                let borrowed = buf.borrow();
70                assert_eq!(borrowed.len(), 10);
71                // All values should be initialized to 0
72                assert!(borrowed.iter().all(|&x| x == 0));
73            }
74            _ => panic!("Expected I16Buffer"),
75        }
76    }
77
78    #[test]
79    fn test_i16_buffer_create_large() {
80        let mut interp = setup_interpreter();
81
82        // Create a buffer of size 1000
83        interp.push(Value::Int32(1000));
84        let result = i16_buffer_builtin(&mut interp);
85        assert!(result.is_ok());
86
87        let buffer = interp.pop().unwrap();
88        match buffer {
89            Value::I16Buffer(buf) => {
90                assert_eq!(buf.borrow().len(), 1000);
91            }
92            _ => panic!("Expected I16Buffer"),
93        }
94    }
95
96    #[test]
97    fn test_i16_buffer_stack_underflow() {
98        let mut interp = setup_interpreter();
99
100        // Try to create buffer without size on stack
101        let result = i16_buffer_builtin(&mut interp);
102        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
103    }
104
105    #[test]
106    fn test_i16_buffer_type_error() {
107        let mut interp = setup_interpreter();
108
109        // Push a non-integer value
110        interp.push(Value::String("not a number".into()));
111        let result = i16_buffer_builtin(&mut interp);
112        assert!(matches!(result, Err(RuntimeError::TypeError(_))));
113    }
114}