1use crate::Artichoke;
2use crate::convert::{BoxUnboxVmValue, UnboxRubyError};
3use crate::core::{Convert, TryConvert, TryConvertMut, Value as _};
4use crate::error::Error;
5use crate::extn::core::array::Array;
6use crate::types::{Ruby, Rust};
7use crate::value::Value;
8
9impl TryConvertMut<&[Value], Value> for Artichoke {
10 type Error = Error;
11
12 fn try_convert_mut(&mut self, value: &[Value]) -> Result<Value, Self::Error> {
13 let ary = Array::from(value);
14 let value = Array::alloc_value(ary, self)?;
15 Ok(self.protect(value))
16 }
17}
18
19impl TryConvertMut<Vec<Value>, Value> for Artichoke {
20 type Error = Error;
21
22 fn try_convert_mut(&mut self, value: Vec<Value>) -> Result<Value, Self::Error> {
23 let ary = Array::from(value);
24 let value = Array::alloc_value(ary, self)?;
25 Ok(self.protect(value))
26 }
27}
28
29impl TryConvertMut<&[Option<Value>], Value> for Artichoke {
30 type Error = Error;
31
32 fn try_convert_mut(&mut self, value: &[Option<Value>]) -> Result<Value, Self::Error> {
33 let ary = value.iter().collect();
34 let value = Array::alloc_value(ary, self)?;
35 Ok(self.protect(value))
36 }
37}
38
39impl TryConvertMut<Vec<Vec<u8>>, Value> for Artichoke {
40 type Error = Error;
41
42 fn try_convert_mut(&mut self, value: Vec<Vec<u8>>) -> Result<Value, Self::Error> {
43 let ary = value
44 .into_iter()
45 .map(|item| self.try_convert_mut(item))
46 .collect::<Result<Array, _>>()?;
47 let value = Array::alloc_value(ary, self)?;
48 Ok(self.protect(value))
49 }
50}
51
52impl TryConvertMut<Vec<&[u8]>, Value> for Artichoke {
53 type Error = Error;
54
55 fn try_convert_mut(&mut self, value: Vec<&[u8]>) -> Result<Value, Self::Error> {
56 let ary = value
57 .into_iter()
58 .map(|item| self.try_convert_mut(item))
59 .collect::<Result<Array, _>>()?;
60 let value = Array::alloc_value(ary, self)?;
61 Ok(self.protect(value))
62 }
63}
64
65impl TryConvertMut<&[Vec<u8>], Value> for Artichoke {
66 type Error = Error;
67
68 fn try_convert_mut(&mut self, value: &[Vec<u8>]) -> Result<Value, Self::Error> {
69 let ary = value
70 .iter()
71 .map(|item| self.try_convert_mut(item.as_slice()))
72 .collect::<Result<Array, _>>()?;
73 let value = Array::alloc_value(ary, self)?;
74 Ok(self.protect(value))
75 }
76}
77
78impl TryConvertMut<&[&[u8]], Value> for Artichoke {
79 type Error = Error;
80
81 fn try_convert_mut(&mut self, value: &[&[u8]]) -> Result<Value, Self::Error> {
82 let ary = value
83 .iter()
84 .copied()
85 .map(|item| self.try_convert_mut(item))
86 .collect::<Result<Array, _>>()?;
87 let value = Array::alloc_value(ary, self)?;
88 Ok(self.protect(value))
89 }
90}
91
92impl TryConvertMut<Vec<String>, Value> for Artichoke {
93 type Error = Error;
94
95 fn try_convert_mut(&mut self, value: Vec<String>) -> Result<Value, Self::Error> {
96 let ary = value
97 .into_iter()
98 .map(|item| self.try_convert_mut(item))
99 .collect::<Result<Array, _>>()?;
100 let value = Array::alloc_value(ary, self)?;
101 Ok(self.protect(value))
102 }
103}
104
105impl TryConvertMut<Vec<&str>, Value> for Artichoke {
106 type Error = Error;
107
108 fn try_convert_mut(&mut self, value: Vec<&str>) -> Result<Value, Self::Error> {
109 let ary = value
110 .into_iter()
111 .map(|item| self.try_convert_mut(item))
112 .collect::<Result<Array, _>>()?;
113 let value = Array::alloc_value(ary, self)?;
114 Ok(self.protect(value))
115 }
116}
117
118impl TryConvertMut<&[String], Value> for Artichoke {
119 type Error = Error;
120
121 fn try_convert_mut(&mut self, value: &[String]) -> Result<Value, Self::Error> {
122 let ary = value
123 .iter()
124 .map(|item| self.try_convert_mut(item.as_str()))
125 .collect::<Result<Array, _>>()?;
126 let value = Array::alloc_value(ary, self)?;
127 Ok(self.protect(value))
128 }
129}
130
131impl TryConvertMut<&[&str], Value> for Artichoke {
132 type Error = Error;
133
134 fn try_convert_mut(&mut self, value: &[&str]) -> Result<Value, Self::Error> {
135 let ary = value
136 .iter()
137 .copied()
138 .map(|item| self.try_convert_mut(item))
139 .collect::<Result<Array, _>>()?;
140 let value = Array::alloc_value(ary, self)?;
141 Ok(self.protect(value))
142 }
143}
144
145impl TryConvertMut<Vec<i64>, Value> for Artichoke {
146 type Error = Error;
147
148 fn try_convert_mut(&mut self, value: Vec<i64>) -> Result<Value, Self::Error> {
149 let iter = value.into_iter().map(|item| self.convert(item));
150 let ary = iter.collect();
151 let value = Array::alloc_value(ary, self)?;
152 Ok(self.protect(value))
153 }
154}
155
156impl TryConvertMut<&[i64], Value> for Artichoke {
157 type Error = Error;
158
159 fn try_convert_mut(&mut self, value: &[i64]) -> Result<Value, Self::Error> {
160 let iter = value.iter().copied().map(|item| self.convert(item));
161 let ary = iter.collect();
162 let value = Array::alloc_value(ary, self)?;
163 Ok(self.protect(value))
164 }
165}
166
167impl TryConvertMut<&[Option<Vec<u8>>], Value> for Artichoke {
168 type Error = Error;
169
170 fn try_convert_mut(&mut self, value: &[Option<Vec<u8>>]) -> Result<Value, Self::Error> {
171 let ary = value
172 .iter()
173 .map(|item| self.try_convert_mut(item.as_deref()))
174 .collect::<Result<Array, _>>()?;
175 let value = Array::alloc_value(ary, self)?;
176 Ok(self.protect(value))
177 }
178}
179
180impl TryConvertMut<Vec<Option<Vec<u8>>>, Value> for Artichoke {
181 type Error = Error;
182
183 fn try_convert_mut(&mut self, value: Vec<Option<Vec<u8>>>) -> Result<Value, Self::Error> {
184 let ary = value
185 .into_iter()
186 .map(|item| self.try_convert_mut(item))
187 .collect::<Result<Array, _>>()?;
188 let value = Array::alloc_value(ary, self)?;
189 Ok(self.protect(value))
190 }
191}
192
193impl TryConvertMut<&[Option<&[u8]>], Value> for Artichoke {
194 type Error = Error;
195
196 fn try_convert_mut(&mut self, value: &[Option<&[u8]>]) -> Result<Value, Self::Error> {
197 let ary = value
198 .iter()
199 .copied()
200 .map(|item| self.try_convert_mut(item))
201 .collect::<Result<Array, _>>()?;
202 let value = Array::alloc_value(ary, self)?;
203 Ok(self.protect(value))
204 }
205}
206
207impl TryConvertMut<Vec<Option<&[u8]>>, Value> for Artichoke {
208 type Error = Error;
209
210 fn try_convert_mut(&mut self, value: Vec<Option<&[u8]>>) -> Result<Value, Self::Error> {
211 let ary = value
212 .into_iter()
213 .map(|item| self.try_convert_mut(item))
214 .collect::<Result<Array, _>>()?;
215 let value = Array::alloc_value(ary, self)?;
216 Ok(self.protect(value))
217 }
218}
219
220impl TryConvertMut<Vec<Vec<Option<Vec<u8>>>>, Value> for Artichoke {
221 type Error = Error;
222
223 fn try_convert_mut(&mut self, value: Vec<Vec<Option<Vec<u8>>>>) -> Result<Value, Self::Error> {
224 let ary = value
225 .into_iter()
226 .map(|item| self.try_convert_mut(item))
227 .collect::<Result<Array, _>>()?;
228 let value = Array::alloc_value(ary, self)?;
229 Ok(self.protect(value))
230 }
231}
232
233impl TryConvertMut<Vec<Vec<Option<&[u8]>>>, Value> for Artichoke {
234 type Error = Error;
235
236 fn try_convert_mut(&mut self, value: Vec<Vec<Option<&[u8]>>>) -> Result<Value, Self::Error> {
237 let ary = value
238 .into_iter()
239 .map(|item| self.try_convert_mut(item))
240 .collect::<Result<Array, _>>()?;
241 let value = Array::alloc_value(ary, self)?;
242 Ok(self.protect(value))
243 }
244}
245
246impl TryConvertMut<&[Option<&str>], Value> for Artichoke {
247 type Error = Error;
248
249 fn try_convert_mut(&mut self, value: &[Option<&str>]) -> Result<Value, Self::Error> {
250 let ary = value
251 .iter()
252 .copied()
253 .map(|item| self.try_convert_mut(item))
254 .collect::<Result<Array, _>>()?;
255 let value = Array::alloc_value(ary, self)?;
256 Ok(self.protect(value))
257 }
258}
259
260impl TryConvertMut<Vec<Option<&str>>, Value> for Artichoke {
261 type Error = Error;
262
263 fn try_convert_mut(&mut self, value: Vec<Option<&str>>) -> Result<Value, Self::Error> {
264 let ary = value
265 .into_iter()
266 .map(|item| self.try_convert_mut(item))
267 .collect::<Result<Array, _>>()?;
268 let value = Array::alloc_value(ary, self)?;
269 Ok(self.protect(value))
270 }
271}
272
273impl TryConvertMut<Vec<Vec<Option<&str>>>, Value> for Artichoke {
274 type Error = Error;
275
276 fn try_convert_mut(&mut self, value: Vec<Vec<Option<&str>>>) -> Result<Value, Self::Error> {
277 let ary = value
278 .into_iter()
279 .map(|item| self.try_convert_mut(item))
280 .collect::<Result<Array, _>>()?;
281 let value = Array::alloc_value(ary, self)?;
282 Ok(self.protect(value))
283 }
284}
285
286impl TryConvertMut<Value, Vec<Value>> for Artichoke {
287 type Error = Error;
288
289 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Value>, Self::Error> {
290 let Ruby::Array = value.ruby_type() else {
291 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
292 };
293 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
294 Ok(array.iter().collect())
295 }
296}
297
298impl TryConvertMut<Value, Vec<Vec<u8>>> for Artichoke {
299 type Error = Error;
300
301 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Vec<u8>>, Self::Error> {
302 let Ruby::Array = value.ruby_type() else {
303 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
304 };
305 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
306 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
307 }
308}
309
310impl TryConvertMut<Value, Vec<Option<Vec<u8>>>> for Artichoke {
311 type Error = Error;
312
313 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Option<Vec<u8>>>, Self::Error> {
314 let Ruby::Array = value.ruby_type() else {
315 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
316 };
317 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
318 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
319 }
320}
321
322impl<'a> TryConvertMut<Value, Vec<&'a [u8]>> for Artichoke {
323 type Error = Error;
324
325 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<&'a [u8]>, Self::Error> {
326 let Ruby::Array = value.ruby_type() else {
327 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
328 };
329 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
330 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
331 }
332}
333
334impl<'a> TryConvertMut<Value, Vec<Option<&'a [u8]>>> for Artichoke {
335 type Error = Error;
336
337 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Option<&'a [u8]>>, Self::Error> {
338 let Ruby::Array = value.ruby_type() else {
339 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
340 };
341 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
342 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
343 }
344}
345
346impl TryConvertMut<Value, Vec<String>> for Artichoke {
347 type Error = Error;
348
349 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<String>, Self::Error> {
350 let Ruby::Array = value.ruby_type() else {
351 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
352 };
353 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
354 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
355 }
356}
357
358impl TryConvertMut<Value, Vec<Option<String>>> for Artichoke {
359 type Error = Error;
360
361 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Option<String>>, Self::Error> {
362 let Ruby::Array = value.ruby_type() else {
363 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
364 };
365 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
366 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
367 }
368}
369
370impl<'a> TryConvertMut<Value, Vec<&'a str>> for Artichoke {
371 type Error = Error;
372
373 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<&'a str>, Self::Error> {
374 let Ruby::Array = value.ruby_type() else {
375 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
376 };
377 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
378 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
379 }
380}
381
382impl<'a> TryConvertMut<Value, Vec<Option<&'a str>>> for Artichoke {
383 type Error = Error;
384
385 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<Option<&'a str>>, Self::Error> {
386 let Ruby::Array = value.ruby_type() else {
387 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
388 };
389 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
390 array.iter().map(|elem| self.try_convert_mut(elem)).collect()
391 }
392}
393
394impl TryConvertMut<Value, Vec<i64>> for Artichoke {
395 type Error = Error;
396
397 fn try_convert_mut(&mut self, mut value: Value) -> Result<Vec<i64>, Self::Error> {
398 let Ruby::Array = value.ruby_type() else {
399 return Err(UnboxRubyError::new(&value, Rust::Vec).into());
400 };
401 let array = unsafe { Array::unbox_from_value(&mut value, self)? };
402 array.iter().map(|elem| self.try_convert(elem)).collect()
403 }
404}
405
406#[cfg(test)]
407mod tests {
408 use crate::test::prelude::*;
409
410 #[test]
411 fn fail_convert() {
412 let mut interp = interpreter();
413 let value = interp.eval(b"Object.new").unwrap();
415 let result = value.try_convert_into_mut::<Vec<Value>>(&mut interp);
416 assert!(result.is_err());
417 }
418
419 #[test]
420 fn prop_arr_int_borrowed() {
421 let mut interp = interpreter();
422 run_arbitrary::<Vec<i64>>(|arr| {
423 let value = interp.try_convert_mut(arr.clone()).unwrap();
425 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
426 let len = len.try_convert_into::<usize>(&interp).unwrap();
427 assert_eq!(len, arr.len());
428
429 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
430 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
431 assert_eq!(empty, arr.is_empty());
432
433 let recovered: Vec<i64> = interp.try_convert_mut(value).unwrap();
434 assert_eq!(recovered, arr);
435 });
436 }
437
438 #[test]
439 fn prop_arr_int_owned() {
440 let mut interp = interpreter();
441 run_arbitrary::<Vec<i64>>(|arr| {
442 let value = interp.try_convert_mut(arr.clone()).unwrap();
444 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
445 let len = len.try_convert_into::<usize>(&interp).unwrap();
446 assert_eq!(len, arr.len());
447
448 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
449 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
450 assert_eq!(empty, arr.is_empty());
451
452 let recovered: Vec<i64> = interp.try_convert_mut(value).unwrap();
453 assert_eq!(recovered, arr);
454 });
455 }
456
457 #[test]
458 fn prop_arr_utf8_borrowed() {
459 let mut interp = interpreter();
460 run_arbitrary::<Vec<String>>(|arr| {
461 let value = interp.try_convert_mut(arr.as_slice()).unwrap();
463 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
464 let len = len.try_convert_into::<usize>(&interp).unwrap();
465 assert_eq!(len, arr.len());
466
467 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
468 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
469 assert_eq!(empty, arr.is_empty());
470
471 let recovered: Vec<String> = interp.try_convert_mut(value).unwrap();
472 assert_eq!(recovered, arr);
473 });
474 }
475
476 #[test]
477 fn prop_arr_utf8_owned() {
478 let mut interp = interpreter();
479 run_arbitrary::<Vec<String>>(|arr| {
480 let value = interp.try_convert_mut(arr.clone()).unwrap();
482 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
483 let len = len.try_convert_into::<usize>(&interp).unwrap();
484 assert_eq!(len, arr.len());
485
486 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
487 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
488 assert_eq!(empty, arr.is_empty());
489
490 let recovered: Vec<String> = interp.try_convert_mut(value).unwrap();
491 assert_eq!(recovered, arr);
492 });
493 }
494
495 #[test]
496 fn prop_arr_nilable_bstr_borrowed() {
497 let mut interp = interpreter();
498 run_arbitrary::<Vec<Option<Vec<u8>>>>(|arr| {
499 let value = interp.try_convert_mut(arr.as_slice()).unwrap();
501 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
502 let len = len.try_convert_into::<usize>(&interp).unwrap();
503 assert_eq!(len, arr.len());
504
505 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
506 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
507 assert_eq!(empty, arr.is_empty());
508
509 let recovered: Vec<Option<Vec<u8>>> = interp.try_convert_mut(value).unwrap();
510 assert_eq!(recovered, arr);
511 });
512 }
513
514 #[test]
515 fn prop_arr_nilable_bstr_owned() {
516 let mut interp = interpreter();
517 run_arbitrary::<Vec<Option<Vec<u8>>>>(|arr| {
518 let value = interp.try_convert_mut(arr.clone()).unwrap();
520 let len = value.funcall(&mut interp, "length", &[], None).unwrap();
521 let len = len.try_convert_into::<usize>(&interp).unwrap();
522 assert_eq!(len, arr.len());
523
524 let empty = value.funcall(&mut interp, "empty?", &[], None).unwrap();
525 let empty = empty.try_convert_into::<bool>(&interp).unwrap();
526 assert_eq!(empty, arr.is_empty());
527
528 let recovered: Vec<Option<Vec<u8>>> = interp.try_convert_mut(value).unwrap();
529 assert_eq!(recovered, arr);
530 });
531 }
532
533 #[test]
534 fn prop_roundtrip_err() {
535 let mut interp = interpreter();
536 run_arbitrary::<i64>(|i| {
537 let value = interp.convert(i);
538 let value = value.try_convert_into_mut::<Vec<Value>>(&mut interp);
539 assert!(value.is_err());
540 });
541 }
542}