Iterate over inner field in struct - rust

I want to implement a Iterator for a struct so easily loop over an inner field but I can't get it to work.
The return from IterWrapper::next() is faulty.
Maybe there is an easier solution to accomplish this.
struct Wrapper {
pub items: Vec<String>
}
struct IterWrapper<'a> {
inner: &'a std::slice::Iter<'a, String>,
}
impl<'a> Iterator for IterWrapper<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next();
}
}
impl Wrapper {
fn iter<'a>(&'a self) -> IterWrapper<'a> {
IterWrapper {
inner: &self.items.iter(),
}
}
}
fn main() {
let w = Wrapper {
items: vec![String::from("test1"), String::from("test2")]
};
for item in w.iter() {
println!("{}", item);
}
}
error[E0308]: mismatched types
--> src/main.rs:13:27
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ---- ^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
14 | self.inner.next();
| - help: consider removing this semicolon
|
= note: expected enum `std::option::Option<&std::string::String>`
found unit type `()`

There are a couple changes that you have to make:
struct Wrapper {
pub items: Vec<String>
}
struct IterWrapper<'a> {
// this needs to own the iterator, not a reference to it
// in order to avoid returning a borrowed value
inner: std::slice::Iter<'a, String>,
}
impl<'a> Iterator for IterWrapper<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
// no semicolon here so the result is implicitly returned
// your old error happened because the semicolon causes the value to not be returned
self.inner.next()
}
}
impl Wrapper {
fn iter<'a>(&'a self) -> IterWrapper<'a> {
IterWrapper {
// give the iterator, not the reference to it
inner: self.items.iter(),
}
}
}
fn main() {
let w = Wrapper {
items: vec![String::from("test1"), String::from("test2")]
};
for item in w.iter() {
println!("{}", item);
}
}

Related

How to specify Rust lifetime when returning item that lives longer than iterator

I'm trying to write an iterator that returns string slices from byte array. I'm having trouble specifying the lifetimes to indicate that the slice can live longer than the iterator.
A simplified test case would be:
struct StrStream<'a> {
data: &'a str,
}
impl<'a> StrStream<'a> {
fn new(data: &'a str) -> Self {
Self { data }
}
fn cstr(&'a mut self, len: usize) -> Option<&'a str> {
Some(self.data.get(0..len).unwrap())
}
}
struct MyIterator<'a> {
i: u32,
stream: &'a mut StrStream<'a>,
}
impl<'a> MyIterator<'a> {
fn new(stream: &'a mut StrStream<'a>) -> Self {
Self { i: 1, stream }
}
}
impl<'a> Iterator for MyIterator<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
self.i += 1;
if self.i < 10 {
return Some(self.stream.cstr(self.i as usize).unwrap());
}
return None;
}
}
#[test]
fn iterates_tokens() {
let mut stream = StrStream::new("abcdefghijklmnopqrstuvwxyz");
let myiter = MyIterator::new(&mut stream);
for item in myiter {
println!(">>>{:?}", item);
}
}
This fails to compile with the error below. Any suggestions how to solve this problem?
error: lifetime may not live long enough
--> xxx/src/tests.rs:32:25
|
26 | impl<'a> Iterator for MyIterator<'a> {
| -- lifetime `'a` defined here
...
29 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
...
32 | return Some(self.stream.cstr(self.i as usize).unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`

Cannot return reference to temporary value with RwLock and iterators

I haven't found an answer to this in other questions.
I have reduced my problem to the following:
use std::sync::RwLock;
pub fn main() {
iter_lock().for_each(|v| {
println!("{}", v);
});
}
fn get_lock<'a>() -> &'a RwLock<Vec<u32>> {
static mut lock: RwLock<Vec<u32>> = RwLock::new(Vec::new());
unsafe { &lock }
}
fn iter_lock<'a>() -> impl std::iter::Iterator<Item = &'a u32> {
get_lock().read().unwrap().iter()
}
playground
The code above will not compile and give the following error:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:15:5
|
15 | get_lock().read().unwrap().iter()
| --------------------------^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
|
= help: use `.collect()` to allocate the iterator
Note that the static mut is not necessary in the code above, but I need it because I need to define a variable inside of an impl block.
I need to return an iterator, not a Vec because I am trying to avoid any allocations, and this function will always be used to iterate.
How can I solve this issue? I'm not afraid of using unsafe code, so unsafe suggestions are also welcome.
You can try something like this:
use std::sync::{RwLock, RwLockReadGuard};
pub fn main() {
let data = Data::new(&[1, 2, 3]);
data.iter().for_each(|x| println!("{:?}", x));
}
struct Data {
inner: RwLock<Vec<u32>>,
}
impl Data {
fn new(vec: &[u32]) -> Self {
Self {
inner: RwLock::new(vec.to_vec()),
}
}
fn iter(&self) -> Iter<'_> {
let d = self.inner.read().unwrap();
Iter::new(d)
}
}
struct Iter<'a> {
inner: RwLockReadGuard<'a, Vec<u32>>,
current_index: usize,
}
impl<'a> Iter<'a> {
pub fn new(inner: RwLockReadGuard<'a, Vec<u32>>) -> Iter<'a> {
Self {
inner,
current_index: 0,
}
}
}
impl Iterator for Iter<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index >= self.inner.len() {
return None;
}
let item = &self.inner[self.current_index];
self.current_index += 1;
Some(*item)
}
}

How do you return a reference with a lifetime from an Iterator implementation in Rust? [duplicate]

I have a struct that lazily load data into an inner vector (but for the example this is ommited). Then I am implementing IntoIterator and Iterator for the IntoIterator type:
struct EntryOwned(u32);
struct Entry<'a>(&'a u32);
impl<'a> EntryOwned {
fn to_entry(&'a self) -> Entry<'a> {
Entry(&self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl<'a> LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&'a self, index: usize) -> Option<Entry<'a>> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl<'a> IntoIterator for &'a mut LazyStruct {
type Item = Entry<'a>;
type IntoIter = LazyStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter<'a> {
inner: &'a mut LazyStruct,
current_index: usize,
}
impl<'a> LazyStructIter<'a> {
fn next_item(&'a mut self) -> Option<Entry<'a>> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl<'a> Iterator for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
Which yields me to a lifetime issue:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 63:5...
--> src/main.rs:63:5
|
63 | / fn next(&mut self) -> Option<Self::Item> {
64 | | self.next_item()
65 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:64:9
|
64 | self.next_item()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 60:6...
--> src/main.rs:60:6
|
60 | impl<'a> Iterator for LazyStructIter<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
= note: expected `&mut LazyStructIter<'_>`
found `&mut LazyStructIter<'a>`
The lifetime of the references should be bind to the LazyStruct, but I cannot change the Iter trait do not accept any lifetime specifier.
I have already check some answers to similar issues:
Iterator returning items by reference, lifetime issue
How do I write an iterator that returns references to itself?
EDIT: The Entry is a more complex data structure and it is not possible to copy it. I have to bind it to a specific lifetime since it contains references to things.
One of them points that the iterator should hold a reference to the original collection instead of owning it since it is not allowed to return a reference with the self lifetime. But I could't make it work.
So, how should I play the references here?
Here is the playground example
You can't.
You require that each item returned by next() has a reference with a lifetime tied to the
existence of the LazyStructIter iterator.
This it is not possible with the Iterator interface:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
But it would be possible with a trait defined as:
trait FakeIterator<'a> {
type Item;
fn next(&'a mut self) -> std::option::Option<Self::Item>;
}
impl<'a> FakeIterator<'a> for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&'a mut self) -> Option<Self::Item> {
self.next_item()
}
}
Tha capability to have a kind of iterator which returns items borrowing from self is the goal of
RFC 1598 - GAT.
See also this article for a collection of workarounds about this topic.
Generally you don't need to specify lifetimes in rust unless 1 of two things is true, the reference is bound to an owner that isn't known, or a reference that is static. Rust says it expected '_ lifetime, which means it understands the ownership and borrows on its own.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c54f5f2f24e635dcfaa0fcbf69fa4ce0
struct EntryOwned(u32);
struct Entry(u32);
impl EntryOwned {
fn to_entry(&self) -> Entry {
Entry(self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&self, index: usize) -> Option<Entry> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl IntoIterator for LazyStruct {
type Item = Entry;
type IntoIter = LazyStructIter;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter {
inner: LazyStruct,
current_index: usize,
}
impl LazyStructIter {
fn next_item(&mut self) -> Option<Entry> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl Iterator for LazyStructIter {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
fn main() {
// let json_data = r#"{"item_1" : 10, "item_2" : 100, "item_3" : 1000}"#;
// if let Ok(data) = serde_json::from_str::<A>(json_data) {
// println!("{:?}", data);
// }
// else if let Ok(data) = serde_json::from_str::<B>(json_data) {
// println!("{:?}", data);
// }
for _ in 0..0 {
println!("foo");
}
}
After removing the lifetime specifications, it compiles fine and runs.

Trouble with digraphs: cannot borrow as mutable

I created a library to deal with digraphs: nodes that link (reference counted) to zero or one other nodes (as in linked lists, but in a digraph a node can be linked to by more than one node).
I am trying to use my library to create a list with a current node:
struct ListWithPointer<'a> {
pub nodes: DigraphNodeRef<String>,
pub current_node: Option<&'a mut DigraphNodeRef<String>>,
}
current_node points to a link in the list.
Now I am trying to move current node to the next element of the list (or to the beginning if the list ended):
fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
if this.current_node.is_some() {
this.current_node.iter_mut().for_each(|a| {
(*a).as_rc_mut().iter_mut()
.for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
});
} else {
this.current_node = Some(&mut this.nodes);
}
}
but whatever I do, it fails with an error like:
error[E0500]: closure requires unique access to `this.current_node` but it is already borrowed
--> src/lib.rs:150:51
|
148 | fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
| -- lifetime `'a` defined here
149 | if this.current_node.is_some() {
150 | this.current_node.iter_mut().for_each(|a| {
| ---------------------------- ^^^ closure construction occurs here
| |
| borrow occurs here
| argument requires that `this.current_node` is borrowed for `'a`
151 | (*a).as_rc_mut().iter_mut()
152 | .for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
| ----------------- second borrow occurs due to use of `this.current_node` in closure
Help to rewrite without errors.
Here is the library code:
use std::sync::Arc;
#[derive(Clone)]
pub struct DigraphNode<T> {
pub next: DigraphNodeRef<T>, // I made it `pub` to be able `item.next.next()` to remove an item from the middle.
data: T,
}
impl<T> DigraphNode<T> {
fn new(next: DigraphNodeRef<T>, data: T) -> Self {
Self { next, data }
}
}
pub struct DigraphNodeRef<T> {
rc: Option<Arc<DigraphNode<T>>>,
}
impl<T> DigraphNodeRef<T> {
pub fn new() -> Self {
Self {
rc: None
}
}
pub fn from_node(value: DigraphNode<T>) -> Self {
Self::from(Some(Arc::new(value)))
}
pub fn from(rc: Option<Arc<DigraphNode<T>>>) -> Self {
Self {
rc
}
}
pub fn as_rc(&self) -> &Option<Arc<DigraphNode<T>>> {
&self.rc
}
pub fn as_rc_mut(&mut self) -> &mut Option<Arc<DigraphNode<T>>> {
&mut self.rc
}
pub fn is_none(&self) -> bool {
self.rc.is_none()
}
pub fn remove(&mut self) -> bool {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
true
} else {
false
}
}
pub fn prepend(&mut self, value: T) -> Self {
let new_node = DigraphNode::new(self.clone(), value);
let new_node_ref = DigraphNodeRef::from_node(new_node);
*self = new_node_ref.clone();
new_node_ref
}
pub fn node(&self) -> Option<DigraphNode<T>>
where T: Clone
{
self.rc.clone().map(|node| (*node).clone())
}
/// TODO: Should return a reference.
pub fn data(&self) -> Option<T>
where T: Clone
{
self.rc.clone().map(|node| (*node).data.clone())
}
pub fn values(self) -> DigraphNodeValuesIterator<T> {
DigraphNodeValuesIterator {
underlying: self.clone()
}
}
}
impl<T> Clone for DigraphNodeRef<T> {
fn clone(&self) -> Self {
Self { rc: self.rc.clone() }
}
}
impl<T> Iterator for DigraphNodeRef<T> {
type Item = Arc<DigraphNode<T>>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
Some(rc.clone())
} else {
None
}
}
}
pub struct DigraphNodeValuesIterator<T> {
underlying: DigraphNodeRef<T>,
}
impl<T: Clone> Iterator for DigraphNodeValuesIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.underlying.next().map(|node| node.data.clone())
}
}
In Rust the mutable access is ensured to be exclusive, i.e. if you hold a reference, some other code can't grab a mutable reference.
Problem is this line:
this.current_node.iter_mut().for_each(...)
It grabs a mutable access to current_node, so it can't regain it again down the line.
Not to mention that iterating over Option is a strange decision.
If you want to move current_node to a different place, I'd try to reorganize your code such that reads are separate from writes, and they are performed in a sequence, instead of trying to do it in one go:
// detach the current_node for moving
if let Some(current_node_to_move) = this.current_node.take() {
let new_current_node_ref: &mut ... = ... // find new location logic
new_current_node_ref.replace(current_node_to_move);
} else {
...
}
Here in line 1 it does a write None update to current_node via this, but immediately relinquishes the mutable reference. Line 2 does a read (search), but also grabs a mutable reference to a new location. Line 3 writes to this location.
To get the linked list implementation right, I recommend https://rust-unofficial.github.io/too-many-lists/

Iterator lifetime issue when returning references to inner collection

I have a struct that lazily load data into an inner vector (but for the example this is ommited). Then I am implementing IntoIterator and Iterator for the IntoIterator type:
struct EntryOwned(u32);
struct Entry<'a>(&'a u32);
impl<'a> EntryOwned {
fn to_entry(&'a self) -> Entry<'a> {
Entry(&self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl<'a> LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&'a self, index: usize) -> Option<Entry<'a>> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl<'a> IntoIterator for &'a mut LazyStruct {
type Item = Entry<'a>;
type IntoIter = LazyStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter<'a> {
inner: &'a mut LazyStruct,
current_index: usize,
}
impl<'a> LazyStructIter<'a> {
fn next_item(&'a mut self) -> Option<Entry<'a>> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl<'a> Iterator for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
Which yields me to a lifetime issue:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 63:5...
--> src/main.rs:63:5
|
63 | / fn next(&mut self) -> Option<Self::Item> {
64 | | self.next_item()
65 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:64:9
|
64 | self.next_item()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 60:6...
--> src/main.rs:60:6
|
60 | impl<'a> Iterator for LazyStructIter<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
= note: expected `&mut LazyStructIter<'_>`
found `&mut LazyStructIter<'a>`
The lifetime of the references should be bind to the LazyStruct, but I cannot change the Iter trait do not accept any lifetime specifier.
I have already check some answers to similar issues:
Iterator returning items by reference, lifetime issue
How do I write an iterator that returns references to itself?
EDIT: The Entry is a more complex data structure and it is not possible to copy it. I have to bind it to a specific lifetime since it contains references to things.
One of them points that the iterator should hold a reference to the original collection instead of owning it since it is not allowed to return a reference with the self lifetime. But I could't make it work.
So, how should I play the references here?
Here is the playground example
You can't.
You require that each item returned by next() has a reference with a lifetime tied to the
existence of the LazyStructIter iterator.
This it is not possible with the Iterator interface:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
But it would be possible with a trait defined as:
trait FakeIterator<'a> {
type Item;
fn next(&'a mut self) -> std::option::Option<Self::Item>;
}
impl<'a> FakeIterator<'a> for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&'a mut self) -> Option<Self::Item> {
self.next_item()
}
}
Tha capability to have a kind of iterator which returns items borrowing from self is the goal of
RFC 1598 - GAT.
See also this article for a collection of workarounds about this topic.
Generally you don't need to specify lifetimes in rust unless 1 of two things is true, the reference is bound to an owner that isn't known, or a reference that is static. Rust says it expected '_ lifetime, which means it understands the ownership and borrows on its own.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c54f5f2f24e635dcfaa0fcbf69fa4ce0
struct EntryOwned(u32);
struct Entry(u32);
impl EntryOwned {
fn to_entry(&self) -> Entry {
Entry(self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&self, index: usize) -> Option<Entry> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl IntoIterator for LazyStruct {
type Item = Entry;
type IntoIter = LazyStructIter;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter {
inner: LazyStruct,
current_index: usize,
}
impl LazyStructIter {
fn next_item(&mut self) -> Option<Entry> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl Iterator for LazyStructIter {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
fn main() {
// let json_data = r#"{"item_1" : 10, "item_2" : 100, "item_3" : 1000}"#;
// if let Ok(data) = serde_json::from_str::<A>(json_data) {
// println!("{:?}", data);
// }
// else if let Ok(data) = serde_json::from_str::<B>(json_data) {
// println!("{:?}", data);
// }
for _ in 0..0 {
println!("foo");
}
}
After removing the lifetime specifications, it compiles fine and runs.

Resources