artichoke_backend/extn/core/array/wrapper.rs
1use core::slice;
2
3#[doc(inline)]
4pub use spinoso_array::RawParts;
5
6use crate::sys;
7use crate::value::Value;
8
9/// A contiguous growable array type based on [`Vec<sys::mrb_value>`](Vec) that
10/// implements the [Ruby `Array`][ruby-array] API for `artichoke-backend` and
11/// `mruby`.
12///
13/// `Array` implements indexing and mutating APIs that make an ideal backend for
14/// the [Ruby `Array` core class][ruby-array]. In practice, this results in less
15/// generic, more single-use APIs. For example, instead of [`Vec::drain`],
16/// `Array` implements [`shift`], [`shift_n`], [`pop`], and [`pop_n`].
17///
18/// Similarly, slicing APIs are more specialized, such as [`first_n`] and
19/// [`last_n`]. Slicing APIs do not return [`Option`], instead preferring to
20/// return an empty slice.
21///
22///
23/// `Array` implements [`BoxUnboxVmValue`] which enables it to be serialized to
24/// a mruby value and unboxed to the Rust `Array` type.
25///
26/// [ruby-array]: https://ruby-doc.org/core-3.1.2/Array.html
27/// [`shift`]: Array::shift
28/// [`shift_n`]: Array::shift_n
29/// [`drop_n`]: Array::drop_n
30/// [`pop`]: Array::pop
31/// [`pop_n`]: Array::pop_n
32/// [`first_n`]: Array::first_n
33/// [`last_n`]: Array::last_n
34/// [`BoxUnboxVmValue`]: crate::convert::BoxUnboxVmValue
35#[derive(Debug, Clone)]
36pub struct Array(spinoso_array::Array<sys::mrb_value>);
37
38impl Default for Array {
39 #[inline]
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45impl From<spinoso_array::Array<sys::mrb_value>> for Array {
46 fn from(buffer: spinoso_array::Array<sys::mrb_value>) -> Self {
47 Self(buffer)
48 }
49}
50
51impl From<Vec<sys::mrb_value>> for Array {
52 fn from(values: Vec<sys::mrb_value>) -> Self {
53 Self(values.into())
54 }
55}
56
57impl From<Vec<Value>> for Array {
58 fn from(values: Vec<Value>) -> Self {
59 Self(values.iter().map(Value::inner).collect())
60 }
61}
62
63impl<'a> From<&'a [sys::mrb_value]> for Array {
64 fn from(values: &'a [sys::mrb_value]) -> Self {
65 Self(values.into())
66 }
67}
68
69impl<'a> From<&'a [Value]> for Array {
70 fn from(values: &'a [Value]) -> Self {
71 Self(values.iter().map(Value::inner).collect())
72 }
73}
74
75impl FromIterator<sys::mrb_value> for Array {
76 fn from_iter<I>(iter: I) -> Self
77 where
78 I: IntoIterator<Item = sys::mrb_value>,
79 {
80 Self(iter.into_iter().collect())
81 }
82}
83
84impl FromIterator<Value> for Array {
85 fn from_iter<I>(iter: I) -> Self
86 where
87 I: IntoIterator<Item = Value>,
88 {
89 Self(iter.into_iter().map(|value| value.inner()).collect())
90 }
91}
92
93impl FromIterator<Option<Value>> for Array {
94 fn from_iter<I>(iter: I) -> Self
95 where
96 I: IntoIterator<Item = Option<Value>>,
97 {
98 let array = iter
99 .into_iter()
100 .map(|value| value.unwrap_or_default().inner())
101 .collect();
102 Self(array)
103 }
104}
105
106impl<'a> FromIterator<&'a Option<Value>> for Array {
107 fn from_iter<I>(iter: I) -> Self
108 where
109 I: IntoIterator<Item = &'a Option<Value>>,
110 {
111 let array = iter
112 .into_iter()
113 .map(|value| value.unwrap_or_default().inner())
114 .collect();
115 Self(array)
116 }
117}
118
119#[derive(Debug)]
120pub struct Iter<'a>(slice::Iter<'a, sys::mrb_value>);
121
122impl Iterator for Iter<'_> {
123 type Item = Value;
124
125 fn next(&mut self) -> Option<Self::Item> {
126 self.0.next().copied().map(Value::from)
127 }
128}
129
130impl<'a> IntoIterator for &'a Array {
131 type Item = Value;
132 type IntoIter = Iter<'a>;
133
134 fn into_iter(self) -> Self::IntoIter {
135 Iter(self.0.iter())
136 }
137}
138
139impl Extend<sys::mrb_value> for Array {
140 fn extend<T>(&mut self, iter: T)
141 where
142 T: IntoIterator<Item = sys::mrb_value>,
143 {
144 self.0.extend(iter);
145 }
146}
147
148impl Extend<Value> for Array {
149 fn extend<T>(&mut self, iter: T)
150 where
151 T: IntoIterator<Item = Value>,
152 {
153 self.0.extend(iter.into_iter().map(|value| value.inner()));
154 }
155}
156
157impl Array {
158 /// Construct a new, empty `Array`.
159 ///
160 /// The vector will not allocate until elements are pushed into it.
161 #[inline]
162 #[must_use]
163 pub const fn new() -> Self {
164 Self(spinoso_array::Array::new())
165 }
166
167 /// Construct a new, empty `Array` with the specified capacity.
168 ///
169 /// The vector will be able to hold exactly `capacity` elements without
170 /// reallocating. If `capacity` is 0, the vector will not allocate.
171 ///
172 /// It is important to note that although the returned vector has the
173 /// _capacity_ specified, the vector will have a zero _length_.
174 #[inline]
175 #[must_use]
176 pub fn with_capacity(capacity: usize) -> Self {
177 Self(spinoso_array::Array::with_capacity(capacity))
178 }
179
180 /// Construct a new two-element `Array` from the given arguments.
181 ///
182 /// The vector is constructed with `capacity` of 2.
183 #[inline]
184 #[must_use]
185 pub fn assoc(first: Value, second: Value) -> Self {
186 Self(spinoso_array::Array::assoc(first.inner(), second.inner()))
187 }
188
189 /// Returns an iterator over the slice.
190 #[inline]
191 #[must_use]
192 pub fn iter(&self) -> Iter<'_> {
193 self.into_iter()
194 }
195
196 /// Extracts a slice containing the entire vector.
197 ///
198 /// Equivalent to `&ary[..]`.
199 #[inline]
200 #[must_use]
201 pub fn as_slice(&self) -> &[sys::mrb_value] {
202 self.0.as_slice()
203 }
204
205 /// Extracts a mutable slice containing the entire vector.
206 ///
207 /// Equivalent to `&mut ary[..]`.
208 #[inline]
209 #[must_use]
210 pub fn as_mut_slice(&mut self) -> &mut [sys::mrb_value] {
211 self.0.as_mut_slice()
212 }
213
214 /// Returns a raw pointer to the vector's buffer.
215 ///
216 /// The caller must ensure that the vector outlives the pointer this
217 /// function returns, or else it will end up pointing to garbage. Modifying
218 /// the vector may cause its buffer to be reallocated, which would also make
219 /// any pointers to it invalid.
220 ///
221 /// The caller must also ensure that the memory the pointer
222 /// (non-transitively) points to is never written to (except inside an
223 /// `UnsafeCell`) using this pointer or any pointer derived from it. If you
224 /// need to mutate the contents of the slice, use
225 /// [`as_mut_ptr`](Self::as_mut_ptr).
226 #[inline]
227 #[must_use]
228 pub fn as_ptr(&self) -> *const sys::mrb_value {
229 self.0.as_ptr()
230 }
231
232 /// Returns an unsafe mutable pointer to the vector's buffer.
233 ///
234 /// The caller must ensure that the vector outlives the pointer this
235 /// function returns, or else it will end up pointing to garbage.
236 /// Modifying the vector may cause its buffer to be reallocated, which would
237 /// also make any pointers to it invalid.
238 ///
239 /// # Examples
240 ///
241 /// This method is primarily used when mutating a `Array` via a raw pointer
242 /// passed over FFI.
243 ///
244 /// See the [`ARY_PTR`] macro in mruby.
245 ///
246 /// [`ARY_PTR`]: https://github.com/artichoke/mruby/blob/d66440864d08f1c3ac5820d45f11df031b7d43c6/include/mruby/array.h#L52
247 #[inline]
248 #[must_use]
249 pub fn as_mut_ptr(&mut self) -> *mut sys::mrb_value {
250 self.0.as_mut_ptr()
251 }
252
253 /// Set the vector's length without dropping or moving out elements
254 ///
255 /// This method is unsafe because it changes the notion of the number of
256 /// "valid" elements in the vector. Use with care.
257 ///
258 /// # Safety
259 ///
260 /// - `new_len` must be less than or equal to `capacity()`.
261 /// - The elements at `old_len..new_len` must be initialized.
262 ///
263 /// # Examples
264 ///
265 /// This method is primarily used when mutating a `Array` via a raw pointer
266 /// passed over FFI.
267 ///
268 /// See the [`ARY_PTR`] macro in mruby.
269 ///
270 /// [`ARY_PTR`]: https://github.com/artichoke/mruby/blob/d66440864d08f1c3ac5820d45f11df031b7d43c6/include/mruby/array.h#L52
271 #[inline]
272 pub unsafe fn set_len(&mut self, new_len: usize) {
273 self.0.set_len(new_len);
274 }
275
276 /// Creates an `Array` directly from the raw components of another array.
277 ///
278 /// # Safety
279 ///
280 /// This is highly unsafe, due to the number of invariants that aren't
281 /// checked:
282 ///
283 /// - `ptr` needs to have been previously allocated via `Array<T>` (at
284 /// least, it's highly likely to be incorrect if it wasn't).
285 /// - `T` needs to have the same size and alignment as what `ptr` was
286 /// allocated with. (`T` having a less strict alignment is not sufficient,
287 /// the alignment really needs to be equal to satisfy the `dealloc`
288 /// requirement that memory must be allocated and deallocated with the
289 /// same layout.)
290 /// - `length` needs to be less than or equal to `capacity`.
291 /// - `capacity` needs to be the `capacity` that the pointer was allocated
292 /// with.
293 ///
294 /// Violating these may cause problems like corrupting the allocator's
295 /// internal data structures.
296 ///
297 /// The ownership of `ptr` is effectively transferred to the `Array<T>`
298 /// which may then deallocate, reallocate or change the contents of memory
299 /// pointed to by the pointer at will. Ensure that nothing else uses the
300 /// pointer after calling this function.
301 #[must_use]
302 pub unsafe fn from_raw_parts(raw_parts: RawParts<sys::mrb_value>) -> Self {
303 let array = spinoso_array::Array::from_raw_parts(raw_parts);
304 Self(array)
305 }
306
307 /// Decomposes an `Array<T>` into its raw components.
308 ///
309 /// Returns the raw pointer to the underlying data, the length of the array
310 /// (in elements), and the allocated capacity of the data (in elements).
311 ///
312 /// After calling this function, the caller is responsible for the memory
313 /// previously managed by the `Array`. The only way to do this is to convert
314 /// the raw pointer, length, and capacity back into a `Array` with the
315 /// [`from_raw_parts`] function, allowing the destructor to perform the
316 /// cleanup.
317 ///
318 /// [`from_raw_parts`]: Array::from_raw_parts
319 #[must_use]
320 pub fn into_raw_parts(self) -> RawParts<sys::mrb_value> {
321 self.0.into_raw_parts()
322 }
323
324 /// Consume the array and return its elements as a [`Vec<T>`].
325 ///
326 /// For `Array`, this is a cheap operation that unwraps the inner `Vec`.
327 ///
328 /// [`Vec<T>`]: std::vec::Vec
329 #[inline]
330 #[must_use]
331 pub fn into_vec(self) -> Vec<sys::mrb_value> {
332 self.0.into_vec()
333 }
334
335 /// Converts the vector into [`Box<[T]>`](Box).
336 ///
337 /// This will drop any excess capacity.
338 #[inline]
339 #[must_use]
340 pub fn into_boxed_slice(self) -> Box<[sys::mrb_value]> {
341 self.0.into_boxed_slice()
342 }
343
344 /// Returns the number of elements the vector can hold without reallocating.
345 #[inline]
346 #[must_use]
347 pub fn capacity(&self) -> usize {
348 self.0.capacity()
349 }
350
351 /// Reserves capacity for at least `additional` more elements to be inserted
352 /// in the given `Array<T>`. The collection may reserve more space to avoid
353 /// frequent reallocations. After calling reserve, capacity will be greater
354 /// than or equal to `self.len() + additional`. Does nothing if capacity is
355 /// already sufficient.
356 ///
357 /// # Panics
358 ///
359 /// Panics if the new capacity overflows `usize`.
360 #[inline]
361 pub fn reserve(&mut self, additional: usize) {
362 self.0.reserve(additional);
363 }
364
365 /// Shrinks the capacity of the vector as much as possible.
366 ///
367 /// It will drop down as close as possible to the length but the allocator
368 /// may still inform the vector that there is space for a few more elements.
369 #[inline]
370 pub fn shrink_to_fit(&mut self) {
371 self.0.shrink_to_fit();
372 }
373
374 /// Clears the vector, removing all values.
375 ///
376 /// Note that this method has no effect on the allocated capacity of the
377 /// vector.
378 #[inline]
379 pub fn clear(&mut self) {
380 self.0.clear();
381 }
382
383 /// Returns the number of elements in the vector, also referred to as its
384 /// "length".
385 #[inline]
386 #[must_use]
387 pub fn len(&self) -> usize {
388 self.0.len()
389 }
390
391 /// Returns `true` if the vector contains no elements.
392 #[inline]
393 #[must_use]
394 pub fn is_empty(&self) -> bool {
395 self.0.is_empty()
396 }
397
398 /// Returns a reference to an element at the index.
399 ///
400 /// Unlike [`Vec`], this method does not support indexing with a range. See
401 /// the [`slice`](Self::slice) method for retrieving a sub-slice from the
402 /// array.
403 #[inline]
404 #[must_use]
405 pub fn get(&self, index: usize) -> Option<Value> {
406 self.0.get(index).copied().map(Value::from)
407 }
408
409 /// Deletes the element at the specified `index`, returning that element, or
410 /// [`None`] if the `index` is out of range.
411 #[inline]
412 #[must_use]
413 pub fn delete_at(&mut self, index: usize) -> Option<Value> {
414 self.0.delete_at(index).map(Value::from)
415 }
416
417 /// Returns the first element from the vector, or [`None`] if the vector is
418 /// empty.
419 ///
420 /// To retrieve a slice of the first elements in the vector, use
421 /// [`first_n`](Self::first_n).
422 #[inline]
423 #[must_use]
424 pub fn first(&self) -> Option<Value> {
425 self.0.first().copied().map(Value::from)
426 }
427
428 /// Returns up to `n` of the first elements from the vector, or `&[]` if the
429 /// vector is empty.
430 ///
431 /// To retrieve only the first element in the vector, use
432 /// [`first`](Self::first).
433 #[inline]
434 #[must_use]
435 pub fn first_n(&self, n: usize) -> &[sys::mrb_value] {
436 self.0.first_n(n)
437 }
438
439 /// Returns the last element from the vector, or [`None`] if the vector is
440 /// empty.
441 ///
442 /// To retrieve a slice of the last elements in the vector, use
443 /// [`last_n`](Self::last_n).
444 #[inline]
445 #[must_use]
446 pub fn last(&self) -> Option<Value> {
447 self.0.last().copied().map(Value::from)
448 }
449
450 /// Returns up to `n` of the last elements from the vector, or `&[]` if the
451 /// vector is empty.
452 ///
453 /// To retrieve only the last element in the vector, use
454 /// [`last`](Self::last).
455 #[inline]
456 #[must_use]
457 pub fn last_n(&self, n: usize) -> &[sys::mrb_value] {
458 self.0.last_n(n)
459 }
460
461 /// Returns a slice of the underlying vector that includes only the first
462 /// `n` elements.
463 ///
464 /// If `n` is greater than or equal to the length of the vector, `&self[..]`
465 /// is returned.
466 ///
467 /// The inverse of this operation is [`drop_n`](Self::drop_n).
468 #[inline]
469 #[must_use]
470 pub fn take_n(&self, n: usize) -> &[sys::mrb_value] {
471 self.0.take_n(n)
472 }
473
474 /// Returns a slice of the underlying vector that excludes the first `n`
475 /// elements.
476 ///
477 /// If `n` is greater than or equal to the length of the vector, `&[]` is
478 /// returned.
479 ///
480 /// The inverse of this operation is [`take_n`](Self::take_n).
481 #[inline]
482 #[must_use]
483 pub fn drop_n(&self, n: usize) -> &[sys::mrb_value] {
484 self.0.drop_n(n)
485 }
486
487 /// Removes the last element from the vector and returns it, or [`None`] if
488 /// the vector is empty.
489 ///
490 /// To pop more than one element from the end of the vector, use
491 /// [`pop_n`](Self::pop_n).
492 #[inline]
493 #[must_use]
494 pub fn pop(&mut self) -> Option<Value> {
495 self.0.pop().map(Value::from)
496 }
497
498 /// Removes the last `n` elements from the vector.
499 ///
500 /// To pop a single element from the end of the vector, use
501 /// [`pop`](Self::pop).
502 #[inline]
503 #[must_use]
504 pub fn pop_n(&mut self, n: usize) -> Self {
505 Self(self.0.pop_n(n))
506 }
507
508 /// Appends an element to the back of the vector.
509 ///
510 /// To push more than one element to the end of the vector, use
511 /// [`concat`](Self::concat) or `extend`.
512 ///
513 /// # Panics
514 ///
515 /// Panics if the number of elements in the vector overflows a `usize`.
516 #[inline]
517 pub fn push(&mut self, elem: Value) {
518 self.0.push(elem.inner());
519 }
520
521 /// Reverses the order of elements of the vector, in place.
522 #[inline]
523 pub fn reverse(&mut self) {
524 self.0.reverse();
525 }
526
527 /// Removes the first element of the vector and returns it (shifting all
528 /// other elements down by one). Returns [`None`] if the vector is empty.
529 ///
530 /// This operation is also known as "pop front".
531 ///
532 /// To remove more than one element from the front of the vector, use
533 /// [`shift_n`](Self::shift_n).
534 #[inline]
535 #[must_use]
536 pub fn shift(&mut self) -> Option<Value> {
537 self.0.shift().map(Value::from)
538 }
539
540 /// Removes the first `n` elements from the vector.
541 ///
542 /// To shift a single element from the front of the vector, use
543 /// [`shift`](Self::shift).
544 #[inline]
545 #[must_use]
546 pub fn shift_n(&mut self, n: usize) -> Self {
547 Self(self.0.shift_n(n))
548 }
549
550 /// Inserts an element to the front of the vector.
551 ///
552 /// To insert more than one element to the front of the vector, use
553 /// [`unshift_n`](Self::unshift_n).
554 ///
555 /// This operation is also known as "prepend".
556 ///
557 /// # Panics
558 ///
559 /// Panics if the number of elements in the vector overflows a `usize`.
560 #[inline]
561 pub fn unshift(&mut self, elem: Value) {
562 self.0.unshift(elem.inner());
563 }
564
565 /// Return a reference to a subslice of the vector.
566 ///
567 /// This function always returns a slice. If the range specified by `start`
568 /// and `end` overlaps the vector (even if only partially), the overlapping
569 /// slice is returned. If the range does not overlap the vector, an empty
570 /// slice is returned.
571 #[inline]
572 #[must_use]
573 pub fn slice(&self, start: usize, len: usize) -> &[sys::mrb_value] {
574 self.0.slice(start, len)
575 }
576}
577
578impl Array
579where
580 sys::mrb_value: Clone,
581{
582 /// Construct a new `Array` with length `len` and all elements set to
583 /// `default`. The `Array` will have capacity `len`.
584 #[inline]
585 #[must_use]
586 pub fn with_len_and_default(len: usize, default: Value) -> Self {
587 Self(spinoso_array::Array::with_len_and_default(len, default.inner()))
588 }
589
590 /// Appends the elements of `other` to self.
591 ///
592 /// Slice version of `extend`. This operation is analogous to "push n".
593 #[inline]
594 pub fn concat(&mut self, other: &[sys::mrb_value]) {
595 self.0.concat(other);
596 }
597
598 /// Prepends the elements of `other` to self.
599 ///
600 /// To insert one element to the front of the vector, use
601 /// [`unshift`](Self::unshift).
602 ///
603 /// This operation is also known as "prepend".
604 ///
605 /// # Panics
606 ///
607 /// Panics if the number of elements in the vector overflows a `usize`.
608 #[inline]
609 pub fn unshift_n(&mut self, other: &[sys::mrb_value]) {
610 self.0.unshift_n(other);
611 }
612}
613
614impl Array
615where
616 sys::mrb_value: Copy,
617{
618 /// Creates a new array by repeating this array `n` times.
619 ///
620 /// This function will not panic. If the resulting `Array`'s capacity would
621 /// overflow, [`None`] is returned.
622 #[must_use]
623 pub fn repeat(&self, n: usize) -> Option<Self> {
624 self.0.repeat(n).map(Self)
625 }
626}
627
628impl Array
629where
630 sys::mrb_value: Default,
631{
632 /// Set element at position `index` within the vector, extending the vector
633 /// with `nil` if `index` is out of bounds.
634 #[inline]
635 pub fn set(&mut self, index: usize, elem: Value) {
636 self.0.set(index, elem.inner());
637 }
638
639 /// Insert element at position `start` within the vector and remove the
640 /// following `drain` elements. If `start` is out of bounds, the vector will
641 /// be extended with `nil`.
642 ///
643 /// This method sets a slice of the `Array` to a single element, including
644 /// the zero-length slice. It is similar in intent to calling
645 /// [`Vec::splice`] with a one-element iterator.
646 ///
647 /// `set_with_drain` will only drain up to the end of the vector.
648 ///
649 /// To set a single element without draining, use [`set`](Self::set).
650 #[inline]
651 pub fn set_with_drain(&mut self, start: usize, drain: usize, elem: Value) -> usize {
652 self.0.set_with_drain(start, drain, elem.inner())
653 }
654}
655
656impl Array
657where
658 sys::mrb_value: Default + Clone,
659{
660 /// Insert the elements from a slice at a position `index` in the vector,
661 /// extending the vector with `nil` if `index` is out of bounds.
662 ///
663 /// This method is similar to [`Vec::splice`] when called with a zero-length
664 /// range.
665 #[inline]
666 pub fn insert_slice(&mut self, index: usize, values: &[sys::mrb_value]) {
667 self.0.insert_slice(index, values);
668 }
669
670 /// Insert the elements from a slice at a position `index` in the vector and
671 /// remove the following `drain` elements. The vector is extended with
672 /// `nil` if `index` is out of bounds.
673 ///
674 /// This method is similar to [`Vec::splice`] when called with a
675 /// nonzero-length range.
676 ///
677 /// When called with `drain == 0`, this method is equivalent to
678 /// [`insert_slice`](Self::insert_slice).
679 ///
680 /// If `drain >= src.len()` or the tail of the vector is replaced, this
681 /// method is efficient. Otherwise, a temporary buffer is used to move the
682 /// elements.
683 #[inline]
684 pub fn set_slice(&mut self, index: usize, drain: usize, values: &[sys::mrb_value]) -> usize {
685 self.0.set_slice(index, drain, values)
686 }
687}