I have a struct, with two fields, one is a String and another is a string slice referencing the previous member. When implementing next I have to omit the lifetime operator and because of this I can't implement and iterator for the described struct.
Here is the code
struct A<'a> {
a: &'a str,
}
struct B<'a> {
b: String,
a: Option<A<'a>>,
}
impl<'a> B<'a> { // this works fine
fn next_(&'a mut self) -> Option<()> {
self.a = Some(A { a: &self.b });
None
}
}
impl<'a> Iterator for B<'a> {
type Item = ();
fn next(&'a mut self) -> Option<()> { // but this fails because Iterator trait don't expect 'a here
self.a = Some(A { a: &self.b });
None
}
}
Here is the error
error[E0308]: method not compatible with trait
--> src/main.rs:131:9
|
131 | fn next(&'a mut self) -> Option<()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&mut test::B<'a>) -> std::option::Option<_>`
found fn pointer `fn(&'a mut test::B<'a>) -> std::option::Option<_>`
note: the anonymous lifetime #1 defined on the method body at 131:9...
--> src/main.rs:131:9
|
131 | / fn next(&'a mut self) -> Option<()> {
132 | | self.a = Some(A { a: &self.b });
133 | |
134 | | None
135 | | }
| |_________^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 129:10
--> src/main.rs:129:10
|
129 | impl<'a> Iterator for B<'a> {
I'm trying to iterate over words of a file, avoid copying. Here is my code
use std::fs;
use std::io::{self, BufRead};
use std::path;
fn main() {}
#[derive(Debug)]
struct Input<'a> {
word: &'a str,
remaining: &'a str,
}
impl<'a> Input<'a> {
fn new(s: &str) -> Input {
Input {
word: "",
remaining: s,
}
}
}
impl<'a> Iterator for Input<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
// This seems over edge cased
let s = self.remaining;
let mut it = s.chars().enumerate();
while let Some((i, c)) = it.next() {
if c.is_whitespace() {
while let Some((j, c)) = it.next() {
if !c.is_whitespace() {
self.word = &s[..i];
self.remaining = &s[j..];
return Some(self.word);
}
}
self.word = &s[..i];
self.remaining = "";
return Some(self.word);
}
}
self.word = &s;
self.remaining = "";
if self.word.is_empty() {
return None;
}
Some(self.word)
}
}
struct InputFile<'a> {
reader: io::BufReader<fs::File>,
line: String,
input: Option<Input<'a>>,
}
impl<'a> InputFile<'a> {
fn open(path: &str) -> io::Result<InputFile> {
Ok(InputFile {
reader: io::BufReader::new(fs::File::open(path)?),
line: String::new(),
input: None,
})
}
}
impl<'a> Iterator for InputFile<'a> {
type Item = String;
fn next(&mut self) -> Option<String> {
while let Ok(readed) = self.reader.read_line(&mut self.line) {
//self.input = Some(Input::new(&self.line));
self.line.clear();
if readed == 0 {
break;
}
}
None
}
}
But I can't implement InputFile
iterator as I was expecting to.