shape_value/
extraction.rs1use crate::context::VMError;
13use crate::datatable::DataTable;
14use crate::slot::ValueSlot;
15use crate::value::Upvalue;
16use crate::value_word::{ArrayView, ValueWord};
17use std::sync::Arc;
18
19#[inline]
21pub fn require_string(nb: &ValueWord) -> Result<&str, VMError> {
22 nb.as_str()
23 .ok_or_else(|| VMError::type_mismatch("string", nb.type_name()))
24}
25
26#[inline]
28pub fn require_arc_string(nb: &ValueWord) -> Result<&Arc<String>, VMError> {
29 nb.as_arc_string()
30 .ok_or_else(|| VMError::type_mismatch("string", nb.type_name()))
31}
32
33#[inline]
37pub fn require_f64(nb: &ValueWord) -> Result<f64, VMError> {
38 nb.as_f64()
39 .ok_or_else(|| VMError::type_mismatch("number", nb.type_name()))
40}
41
42#[inline]
44pub fn require_number(nb: &ValueWord) -> Result<f64, VMError> {
45 nb.as_number_coerce()
46 .ok_or_else(|| VMError::type_mismatch("number", nb.type_name()))
47}
48
49#[inline]
53pub fn require_int(nb: &ValueWord) -> Result<i64, VMError> {
54 nb.as_i64()
55 .ok_or_else(|| VMError::type_mismatch("int", nb.type_name()))
56}
57
58#[inline]
60pub fn require_bool(nb: &ValueWord) -> Result<bool, VMError> {
61 nb.as_bool()
62 .ok_or_else(|| VMError::type_mismatch("bool", nb.type_name()))
63}
64
65#[inline]
69pub fn require_array(nb: &ValueWord) -> Result<ArrayView<'_>, VMError> {
70 nb.as_any_array()
71 .ok_or_else(|| VMError::type_mismatch("array", nb.type_name()))
72}
73
74#[inline]
76pub fn require_datatable(nb: &ValueWord) -> Result<&Arc<DataTable>, VMError> {
77 nb.as_datatable()
78 .ok_or_else(|| VMError::type_mismatch("datatable", nb.type_name()))
79}
80
81#[inline]
83pub fn require_typed_object(nb: &ValueWord) -> Result<(u64, &[ValueSlot], u64), VMError> {
84 nb.as_typed_object()
85 .ok_or_else(|| VMError::type_mismatch("object", nb.type_name()))
86}
87
88#[inline]
90pub fn require_closure(nb: &ValueWord) -> Result<(u16, &[Upvalue]), VMError> {
91 nb.as_closure()
92 .ok_or_else(|| VMError::type_mismatch("closure", nb.type_name()))
93}
94
95#[inline]
99pub fn nb_to_display_string(nb: &ValueWord) -> String {
100 format!("{}", nb)
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use std::sync::Arc;
107
108 #[test]
109 fn test_require_string_ok() {
110 let nb = ValueWord::from_string(Arc::new("hello".to_string()));
111 assert_eq!(require_string(&nb).unwrap(), "hello");
112 }
113
114 #[test]
115 fn test_require_string_err() {
116 let nb = ValueWord::from_f64(42.0);
117 let err = require_string(&nb).unwrap_err();
118 match err {
119 VMError::TypeError { expected, got } => {
120 assert_eq!(expected, "string");
121 assert_eq!(got, "number");
122 }
123 other => panic!("expected TypeError, got {:?}", other),
124 }
125 }
126
127 #[test]
128 fn test_require_number_coerce() {
129 let nb = ValueWord::from_f64(3.14);
131 assert_eq!(require_number(&nb).unwrap(), 3.14);
132
133 let nb = ValueWord::from_i64(42);
135 assert_eq!(require_number(&nb).unwrap(), 42.0);
136
137 let nb = ValueWord::from_string(Arc::new("x".to_string()));
139 assert!(require_number(&nb).is_err());
140 }
141
142 #[test]
143 fn test_require_int() {
144 let nb = ValueWord::from_i64(99);
145 assert_eq!(require_int(&nb).unwrap(), 99);
146
147 let nb = ValueWord::from_f64(1.5);
148 assert!(require_int(&nb).is_err());
149 }
150
151 #[test]
152 fn test_require_bool() {
153 let nb = ValueWord::from_bool(true);
154 assert_eq!(require_bool(&nb).unwrap(), true);
155
156 let nb = ValueWord::from_i64(1);
157 assert!(require_bool(&nb).is_err());
158 }
159
160 #[test]
161 fn test_require_array() {
162 let nb = ValueWord::from_array(Arc::new(vec![ValueWord::from_i64(1)]));
163 assert_eq!(require_array(&nb).unwrap().len(), 1);
164
165 let nb = ValueWord::from_f64(1.0);
166 assert!(require_array(&nb).is_err());
167 }
168
169 #[test]
170 fn test_require_typed_object() {
171 let nb = ValueWord::from_f64(1.0);
172 let err = require_typed_object(&nb).unwrap_err();
173 match err {
174 VMError::TypeError { expected, got } => {
175 assert_eq!(expected, "object");
176 assert_eq!(got, "number");
177 }
178 other => panic!("expected TypeError, got {:?}", other),
179 }
180 }
181
182 #[test]
183 fn test_nb_to_display_string() {
184 assert_eq!(nb_to_display_string(&ValueWord::from_f64(3.14)), "3.14");
185 assert_eq!(nb_to_display_string(&ValueWord::from_i64(42)), "42");
186 assert_eq!(nb_to_display_string(&ValueWord::from_bool(true)), "true");
187 assert_eq!(nb_to_display_string(&ValueWord::none()), "none");
188 let s = ValueWord::from_string(Arc::new("hello".to_string()));
189 assert_eq!(nb_to_display_string(&s), "hello");
190 }
191}