Wasm场景下如何声明元素生命周期与迭代器一致的Rust迭代器?
问题:实现元素生命周期与迭代器绑定的迭代器
最终目标是将Vec<v128>当作Vec<i16>来迭代,遍历v128中打包的i16元素。
初始编译错误
[INFO]: Checking for the Wasm target... [INFO]: Compiling to Wasm... Compiling snakelib v0.1.0 (/home/jeff/gitrepos/code/code/pdfsnake/firebase/webapp/wasm) error: lifetime may not live long enough --> pdfsnake/firebase/webapp/wasm/src/i16word_wasm.rs:214:13 | 207 | impl<'a> Iterator for I16WordIterMut<'a> { | -- lifetime `'a` defined here ... 210 | fn next(&mut self) -> Option<Self::Item> { | - let's call the lifetime of this reference `'1` ... 214 | Some(n) | ^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: could not compile `snakelib` (lib) due to previous error Error: Compiling your crate to WebAssembly failed Caused by: failed to execute `cargo build`: exited with exit status: 101 full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"
相关代码
use core::arch::wasm32; const I16_COUNT: usize = 8; #[derive(Debug, Clone, Copy)] pub struct I16Word { pub w: wasm32::v128 } impl From<&mut I16Word> for [i16; I16_COUNT] { fn from(w: &mut I16Word) -> [i16; I16_COUNT] { [ wasm32::i16x8_extract_lane::<0>(w.w), wasm32::i16x8_extract_lane::<1>(w.w), wasm32::i16x8_extract_lane::<2>(w.w), wasm32::i16x8_extract_lane::<3>(w.w), wasm32::i16x8_extract_lane::<4>(w.w), wasm32::i16x8_extract_lane::<5>(w.w), wasm32::i16x8_extract_lane::<6>(w.w), wasm32::i16x8_extract_lane::<7>(w.w) ] } } impl I16Word { pub fn iter_mut(&mut self) -> I16WordIterMut { let slice: [i16; I16_COUNT] = self.into(); I16WordIterMut { word: slice, i16word: self, index: 0 } } } pub struct I16WordIterMut<'a> { word: [i16; I16_COUNT], i16word: &'a mut I16Word, index: usize } impl<'a> Iterator for I16WordIterMut<'a> { type Item = &'a mut i16; fn next(&mut self) -> Option<Self::Item> { if self.index < I16_COUNT { let n = &mut self.word[self.index]; self.index += 1; Some(n) } else { None } } } impl<'a> Drop for I16WordIterMut<'a> { fn drop(&mut self) { *self.i16word = (&self.word).into(); } }
由于底层wasm32::v128无法直接获取&mut i16,所以在迭代器中保留了一份副本。因为迭代器持有容器的可变引用,其他对象无法读写该容器,因此在迭代器销毁时将内容复制回容器应该是安全的。理解错误信息的含义,但找不到修复方法或替代方案。
更新:采用解决方案后的新错误
采用Chayim的解决方案后,原代码编译通过,但调用代码出现类型不匹配错误:
[INFO]: Checking for the Wasm target... [INFO]: Compiling to Wasm... Compiling snakelib v0.1.0 (/home/jeff/gitrepos/code/code/pdfsnake/firebase/webapp/wasm) error[E0308]: mismatched types --> pdfsnake/firebase/webapp/wasm/src/i16vec.rs:161:26 | 161 | self.j = self.i.next().map(|w| w.iter_mut()); | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<IterMut<'_, i16>>`, found `Option<I16WordIterMut<'_>>` | | | expected due to the type of this binding | = note: expected enum `std::option::Option<std::slice::IterMut<'a, i16>>` found enum `std::option::Option<I16WordIterMut<'_>>` For more information about this error, try `rustc --explain E0308`. error: could not compile `snakelib` (lib) due to previous error Error: Compiling your crate to WebAssembly failed Caused by: failed to execute `cargo build`: exited with exit status: 101 full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"
调用代码
pub struct I16VecIterMut<'a> { i: std::slice::IterMut<'a, I16Word>, j: Option<std::slice::IterMut<'a, i16>>, remaining: usize } impl<'a> Iterator for I16VecIterMut<'a> { type Item = &'a mut i16; fn next(&mut self) -> Option<Self::Item> { if self.remaining < 1 { return None; } self.remaining -= 1; for _ in 0..2 { if self.j.is_none() { self.j = self.i.next().map(|w| w.iter_mut()); } match self.j { Some(ref mut j) => match j.next() { Some(n) => return Some(n), None => { self.j = None; } }, None => return None } } panic!("I16VecIterMut::next() loop error") } }
内容的提问来源于stack exchange,提问作者Jeffrey Rennie
相关产品推荐
相关产品推荐

