uni_core/primitives/
i16_ref.rs1use crate::compat::{format, ToString};
4use crate::interpreter::Interpreter;
5use crate::value::{RuntimeError, Value};
6
7pub fn i16_ref_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
11 let index = interp.pop_integer()?;
12 let buffer_val = interp.pop()?;
13
14 match buffer_val {
15 Value::I16Buffer(buffer) => {
16 let borrowed = buffer.borrow();
17
18 if index >= borrowed.len() {
19 return Err(RuntimeError::DomainError(format!(
20 "Index {} out of bounds for buffer of length {}",
21 index,
22 borrowed.len()
23 )));
24 }
25
26 let value = borrowed[index];
27 interp.push(Value::Int32(value as i32));
29 Ok(())
30 }
31 _ => Err(RuntimeError::TypeError(
32 "i16-ref expects an i16-buffer".to_string(),
33 )),
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use crate::compat::Rc;
41
42 #[cfg(not(target_os = "none"))]
43 use std::cell::RefCell;
44 #[cfg(target_os = "none")]
45 use core::cell::RefCell;
46
47 fn setup_interpreter() -> Interpreter {
48 Interpreter::new()
49 }
50
51 #[test]
52 fn test_i16_ref_basic() {
53 let mut interp = setup_interpreter();
54
55 let buffer = vec![10i16, 20, 30, 40, 50];
57 let buffer_val = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
58
59 interp.push(buffer_val);
61 interp.push(Value::Int32(2));
62 let result = i16_ref_builtin(&mut interp);
63 assert!(result.is_ok());
64
65 let value = interp.pop().unwrap();
66 assert!(matches!(value, Value::Int32(30)));
67 }
68
69 #[test]
70 fn test_i16_ref_first_element() {
71 let mut interp = setup_interpreter();
72
73 let buffer = vec![100i16, 200, 300];
74 let buffer_val = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
75
76 interp.push(buffer_val);
77 interp.push(Value::Int32(0));
78 i16_ref_builtin(&mut interp).unwrap();
79
80 let value = interp.pop().unwrap();
81 assert!(matches!(value, Value::Int32(100)));
82 }
83
84 #[test]
85 fn test_i16_ref_last_element() {
86 let mut interp = setup_interpreter();
87
88 let buffer = vec![10i16, 20, 30];
89 let buffer_val = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
90
91 interp.push(buffer_val);
92 interp.push(Value::Int32(2));
93 i16_ref_builtin(&mut interp).unwrap();
94
95 let value = interp.pop().unwrap();
96 assert!(matches!(value, Value::Int32(30)));
97 }
98
99 #[test]
100 fn test_i16_ref_out_of_bounds() {
101 let mut interp = setup_interpreter();
102
103 let buffer = vec![10i16, 20, 30];
104 let buffer_val = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
105
106 interp.push(buffer_val);
107 interp.push(Value::Int32(5));
108 let result = i16_ref_builtin(&mut interp);
109 assert!(matches!(result, Err(RuntimeError::DomainError(_))));
110 }
111
112 #[test]
113 fn test_i16_ref_negative_values() {
114 let mut interp = setup_interpreter();
115
116 let buffer = vec![-100i16, -200, -300];
117 let buffer_val = Value::I16Buffer(Rc::new(RefCell::new(buffer)));
118
119 interp.push(buffer_val);
120 interp.push(Value::Int32(1));
121 i16_ref_builtin(&mut interp).unwrap();
122
123 let value = interp.pop().unwrap();
124 assert!(matches!(value, Value::Int32(-200)));
125 }
126
127 #[test]
128 fn test_i16_ref_type_error() {
129 let mut interp = setup_interpreter();
130
131 interp.push(Value::Number(42.0));
133 interp.push(Value::Int32(0));
134 let result = i16_ref_builtin(&mut interp);
135 assert!(matches!(result, Err(RuntimeError::TypeError(_))));
136 }
137
138 #[test]
139 fn test_i16_ref_stack_underflow() {
140 let mut interp = setup_interpreter();
141
142 let result = i16_ref_builtin(&mut interp);
144 assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
145 }
146}