From 673e3eb30543fc574cd4dbd7080cbcd9d4d755c2 Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Sun, 11 Jun 2023 19:40:23 +0200 Subject: [PATCH] Implement `IntoIterator` for `Array` --- CHANGELOG.md | 5 +++ crates/js-sys/src/lib.rs | 96 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31d2089be03..00c6a30a45e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ## [Unreleased](https://github.com/rustwasm/wasm-bindgen/compare/0.2.86...main) +### Added + +* Implemented `IntoIterator` for `Array`. + [#3477](https://github.com/rustwasm/wasm-bindgen/pull/3477) + ### Changed * Deprecate `HtmlMenuItemElement` and parts of `HtmlMenuElement`. diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 1f59db05203..576aec1f078 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -610,6 +610,64 @@ extern "C" { pub fn unshift(this: &Array, value: &JsValue) -> u32; } +/// Iterator returned by `Array::into_iter` +#[derive(Debug, Clone)] +pub struct ArrayIntoIter { + range: std::ops::Range, + array: Array, +} + +impl std::iter::Iterator for ArrayIntoIter { + type Item = JsValue; + + fn next(&mut self) -> Option { + let index = self.range.next()?; + Some(self.array.get(index)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } + + #[inline] + fn count(self) -> usize + where + Self: Sized, + { + self.range.count() + } + + #[inline] + fn last(self) -> Option + where + Self: Sized, + { + let Self { range, array } = self; + range.last().map(|index| array.get(index)) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.range.nth(n).map(|index| self.array.get(index)) + } +} + +impl std::iter::DoubleEndedIterator for ArrayIntoIter { + fn next_back(&mut self) -> Option { + let index = self.range.next_back()?; + Some(self.array.get(index)) + } + + fn nth_back(&mut self, n: usize) -> Option { + self.range.nth_back(n).map(|index| self.array.get(index)) + } +} + +impl std::iter::FusedIterator for ArrayIntoIter {} + +impl std::iter::ExactSizeIterator for ArrayIntoIter {} + /// Iterator returned by `Array::iter` #[derive(Debug, Clone)] pub struct ArrayIter<'a> { @@ -629,6 +687,28 @@ impl<'a> std::iter::Iterator for ArrayIter<'a> { fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + + #[inline] + fn count(self) -> usize + where + Self: Sized, + { + self.range.count() + } + + #[inline] + fn last(self) -> Option + where + Self: Sized, + { + let Self { range, array } = self; + range.last().map(|index| array.get(index)) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.range.nth(n).map(|index| self.array.get(index)) + } } impl<'a> std::iter::DoubleEndedIterator for ArrayIter<'a> { @@ -636,6 +716,10 @@ impl<'a> std::iter::DoubleEndedIterator for ArrayIter<'a> { let index = self.range.next_back()?; Some(self.array.get(index)) } + + fn nth_back(&mut self, n: usize) -> Option { + self.range.nth_back(n).map(|index| self.array.get(index)) + } } impl<'a> std::iter::FusedIterator for ArrayIter<'a> {} @@ -665,6 +749,18 @@ impl Array { } } +impl std::iter::IntoIterator for Array { + type Item = JsValue; + type IntoIter = ArrayIntoIter; + + fn into_iter(self) -> Self::IntoIter { + ArrayIntoIter { + range: 0..self.length(), + array: self, + } + } +} + // TODO pre-initialize the Array with the correct length using TrustedLen impl std::iter::FromIterator for Array where