Skip to content

Commit 221514a

Browse files
Pauanalexcrichton
authored andcommitted
Adding in Array::iter and Array::to_vec (#1909)
* Adding in Array::iter and Array::to_vec * Changing ArrayIter to use std::ops::Range
1 parent cbfefb3 commit 221514a

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

crates/js-sys/src/lib.rs

+55
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,61 @@ extern "C" {
425425
pub fn unshift(this: &Array, value: &JsValue) -> u32;
426426
}
427427

428+
/// Iterator returned by `Array::iter`
429+
#[derive(Debug, Clone)]
430+
pub struct ArrayIter<'a> {
431+
range: std::ops::Range<u32>,
432+
array: &'a Array,
433+
}
434+
435+
impl<'a> std::iter::Iterator for ArrayIter<'a> {
436+
type Item = JsValue;
437+
438+
fn next(&mut self) -> Option<Self::Item> {
439+
let index = self.range.next()?;
440+
Some(self.array.get(index))
441+
}
442+
443+
#[inline]
444+
fn size_hint(&self) -> (usize, Option<usize>) {
445+
self.range.size_hint()
446+
}
447+
}
448+
449+
impl<'a> std::iter::DoubleEndedIterator for ArrayIter<'a> {
450+
fn next_back(&mut self) -> Option<Self::Item> {
451+
let index = self.range.next_back()?;
452+
Some(self.array.get(index))
453+
}
454+
}
455+
456+
impl<'a> std::iter::FusedIterator for ArrayIter<'a> {}
457+
458+
impl<'a> std::iter::ExactSizeIterator for ArrayIter<'a> {}
459+
460+
impl Array {
461+
/// Returns an iterator over the values of the JS array.
462+
pub fn iter(&self) -> ArrayIter<'_> {
463+
ArrayIter {
464+
range: 0..self.length(),
465+
array: self,
466+
}
467+
}
468+
469+
/// Converts the JS array into a new Vec.
470+
pub fn to_vec(&self) -> Vec<JsValue> {
471+
let len = self.length();
472+
473+
let mut output = Vec::with_capacity(len as usize);
474+
475+
for i in 0..len {
476+
output.push(self.get(i));
477+
}
478+
479+
output
480+
}
481+
}
482+
428483
// TODO pre-initialize the Array with the correct length using TrustedLen
429484
impl<A> std::iter::FromIterator<A> for Array
430485
where

crates/js-sys/tests/wasm/Array.rs

+63
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,69 @@ fn from_iter() {
8181
);
8282
}
8383

84+
#[wasm_bindgen_test]
85+
fn to_vec() {
86+
let array = vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]
87+
.into_iter()
88+
.collect::<js_sys::Array>();
89+
90+
assert_eq!(array.to_vec(), vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]);
91+
}
92+
93+
#[wasm_bindgen_test]
94+
fn iter() {
95+
let array = vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]
96+
.into_iter()
97+
.collect::<js_sys::Array>();
98+
99+
assert_eq!(array.iter().collect::<Vec<JsValue>>(), vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]);
100+
101+
let mut iter = array.iter();
102+
103+
assert_eq!(iter.size_hint(), (3, Some(3)));
104+
assert_eq!(iter.next(), Some(JsValue::from("a")));
105+
106+
assert_eq!(iter.size_hint(), (2, Some(2)));
107+
assert_eq!(iter.next_back(), Some(JsValue::from("c")));
108+
109+
assert_eq!(iter.size_hint(), (1, Some(1)));
110+
assert_eq!(iter.next_back(), Some(JsValue::from("b")));
111+
112+
assert_eq!(iter.size_hint(), (0, Some(0)));
113+
assert_eq!(iter.next(), None);
114+
115+
assert_eq!(iter.size_hint(), (0, Some(0)));
116+
assert_eq!(iter.next_back(), None);
117+
118+
let mut iter = array.iter();
119+
120+
assert_eq!(iter.size_hint(), (3, Some(3)));
121+
assert_eq!(iter.next(), Some(JsValue::from("a")));
122+
123+
assert_eq!(iter.size_hint(), (2, Some(2)));
124+
assert_eq!(iter.next(), Some(JsValue::from("b")));
125+
126+
assert_eq!(iter.size_hint(), (1, Some(1)));
127+
assert_eq!(iter.next(), Some(JsValue::from("c")));
128+
129+
assert_eq!(iter.size_hint(), (0, Some(0)));
130+
assert_eq!(iter.next(), None);
131+
132+
let mut iter = array.iter();
133+
134+
assert_eq!(iter.size_hint(), (3, Some(3)));
135+
assert_eq!(iter.next_back(), Some(JsValue::from("c")));
136+
137+
assert_eq!(iter.size_hint(), (2, Some(2)));
138+
assert_eq!(iter.next_back(), Some(JsValue::from("b")));
139+
140+
assert_eq!(iter.size_hint(), (1, Some(1)));
141+
assert_eq!(iter.next_back(), Some(JsValue::from("a")));
142+
143+
assert_eq!(iter.size_hint(), (0, Some(0)));
144+
assert_eq!(iter.next_back(), None);
145+
}
146+
84147
#[wasm_bindgen_test]
85148
fn new_with_length() {
86149
let array = Array::new_with_length(5);

0 commit comments

Comments
 (0)