Skip to content

Commit

Permalink
Adding in Array::iter and Array::to_vec (#1909)
Browse files Browse the repository at this point in the history
* Adding in Array::iter and Array::to_vec

* Changing ArrayIter to use std::ops::Range
  • Loading branch information
Pauan authored and alexcrichton committed Dec 17, 2019
1 parent cbfefb3 commit 221514a
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
55 changes: 55 additions & 0 deletions crates/js-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,61 @@ extern "C" {
pub fn unshift(this: &Array, value: &JsValue) -> u32;
}

/// Iterator returned by `Array::iter`
#[derive(Debug, Clone)]
pub struct ArrayIter<'a> {
range: std::ops::Range<u32>,
array: &'a Array,
}

impl<'a> std::iter::Iterator for ArrayIter<'a> {
type Item = JsValue;

fn next(&mut self) -> Option<Self::Item> {
let index = self.range.next()?;
Some(self.array.get(index))
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}

impl<'a> std::iter::DoubleEndedIterator for ArrayIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
let index = self.range.next_back()?;
Some(self.array.get(index))
}
}

impl<'a> std::iter::FusedIterator for ArrayIter<'a> {}

impl<'a> std::iter::ExactSizeIterator for ArrayIter<'a> {}

impl Array {
/// Returns an iterator over the values of the JS array.
pub fn iter(&self) -> ArrayIter<'_> {
ArrayIter {
range: 0..self.length(),
array: self,
}
}

/// Converts the JS array into a new Vec.
pub fn to_vec(&self) -> Vec<JsValue> {
let len = self.length();

let mut output = Vec::with_capacity(len as usize);

for i in 0..len {
output.push(self.get(i));
}

output
}
}

// TODO pre-initialize the Array with the correct length using TrustedLen
impl<A> std::iter::FromIterator<A> for Array
where
Expand Down
63 changes: 63 additions & 0 deletions crates/js-sys/tests/wasm/Array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,69 @@ fn from_iter() {
);
}

#[wasm_bindgen_test]
fn to_vec() {
let array = vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]
.into_iter()
.collect::<js_sys::Array>();

assert_eq!(array.to_vec(), vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]);
}

#[wasm_bindgen_test]
fn iter() {
let array = vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]
.into_iter()
.collect::<js_sys::Array>();

assert_eq!(array.iter().collect::<Vec<JsValue>>(), vec![JsValue::from("a"), JsValue::from("b"), JsValue::from("c")]);

let mut iter = array.iter();

assert_eq!(iter.size_hint(), (3, Some(3)));
assert_eq!(iter.next(), Some(JsValue::from("a")));

assert_eq!(iter.size_hint(), (2, Some(2)));
assert_eq!(iter.next_back(), Some(JsValue::from("c")));

assert_eq!(iter.size_hint(), (1, Some(1)));
assert_eq!(iter.next_back(), Some(JsValue::from("b")));

assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);

assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next_back(), None);

let mut iter = array.iter();

assert_eq!(iter.size_hint(), (3, Some(3)));
assert_eq!(iter.next(), Some(JsValue::from("a")));

assert_eq!(iter.size_hint(), (2, Some(2)));
assert_eq!(iter.next(), Some(JsValue::from("b")));

assert_eq!(iter.size_hint(), (1, Some(1)));
assert_eq!(iter.next(), Some(JsValue::from("c")));

assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);

let mut iter = array.iter();

assert_eq!(iter.size_hint(), (3, Some(3)));
assert_eq!(iter.next_back(), Some(JsValue::from("c")));

assert_eq!(iter.size_hint(), (2, Some(2)));
assert_eq!(iter.next_back(), Some(JsValue::from("b")));

assert_eq!(iter.size_hint(), (1, Some(1)));
assert_eq!(iter.next_back(), Some(JsValue::from("a")));

assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next_back(), None);
}

#[wasm_bindgen_test]
fn new_with_length() {
let array = Array::new_with_length(5);
Expand Down

0 comments on commit 221514a

Please sign in to comment.