I tried to cut out a bunch of code to provide a minimal (non)-working example below.
The basic background is:
- I have a borrowed slice that I'm treating as a circular buffer view
- I'm attempting to implement nom's
InputIter
trait for this struct, but cannot figure out the correct way to specify lifetimes.
impl<'a> RingReader<'a> {
/// Returns the number of elements currently in the ring.
pub fn len(&self) -> usize {
if self.wr < self.rd {
self.wr + self.buffer.len() - self.rd
} else {
self.wr - self.rd
}
}
pub fn get(&self, index: usize) -> u8 {
let pos = (self.rd + index) % (self.buffer.len());
self.buffer[pos]
}
pub fn iter(&self) -> RingIter {
RingIter {
rb: self,
cur: 0,
end: self.len(),
}
}
}
/// Used as reader view into a circular buffer
pub struct RingReader<'a> {
buffer: &'a [u8],
pub rd: usize,
pub wr: usize,
}
pub struct RingIter<'a> {
rb: &'a RingReader<'a>,
cur: usize,
end: usize,
}
impl Iterator for RingIter<'_> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
if self.cur == self.end {
None
} else {
let v = self.rb.get(self.cur);
self.cur += 1;
Some(v)
}
}
}
/// XXX this is actually from the `nom::InputIter` crate
/// - importing here just to make it work on the playground
pub trait InputIter {
/// Example: `u8` for `&[u8]` or `char` for `&str`
type Item;
type IterElem: Iterator<Item = Self::Item>;
fn iter_elements(&self) -> Self::IterElem;
}
impl<'a> InputIter for RingReader<'a> {
type Item = u8;
type IterElem = RingIter<'a>;
fn iter_elements(&self) -> RingIter<'a> {
// TODO: How do I define the lifetime's here?
// - &self is anonymous lifetime?
let ri = RingIter {
rb: self,
cur: 0,
end: self.len(),
};
ri
}
}
fn main() {
let buf = [0, 1, 2, 3];
let ring = RingReader {
buffer: &buf[..],
rd: 0,
wr: 4,
};
// This is OK
for i in ring.iter() {
println!("got: {:?}", i);
}
println!("Hello, world!");
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:73:18
|
73 | let ri = RingIter {
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 70:22...
--> src/main.rs:70:22
|
70 | fn iter_elements(&self) -> RingIter<'a> {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:74:17
|
74 | rb: self,
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 66:6...
--> src/main.rs:66:6
|
66 | impl<'a> InputIter for RingReader<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:78:9
|
78 | ri
| ^^
= note: expected `RingIter<'a>`
found `RingIter<'_>`
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground` due to previous error