I think this is something obvious I'm missing, but here goes..
use std::io;
pub trait Source<'a, T> {
fn push(&self, t: T) -> io::Result<()>;
fn link(&mut self, sink: &dyn Sink<'a, T>) -> io::Result<()>;
}
pub trait Sink<'a, T> {
fn push(&self, t: T) -> io::Result<()>;
fn link(&mut self, source: &dyn Source<T>) -> io::Result<()>;
}
pub struct SyncSource<'a, T> {
sink: Option<&'a dyn Sink<'a, T>>,
}
impl<'a, T> SyncSource<'a, T> {
pub fn new() -> SyncSource<'a, T> {
SyncSource {
sink: None,
}
}
}
impl<'a, T> Source<'a, T> for SyncSource<'a, T> {
fn push(&self, t: T) -> io::Result<()> {
match self.sink {
Some(sink) => sink.push(t),
None => Err(io::Error::new(io::ErrorKind::NotConnected, "no sink")),
}
}
fn link(&mut self, sink: &dyn Sink<'a, T>) -> io::Result<()> {
self.sink = Some(sink);
Ok(())
}
}
pub struct SyncSink<'a, T> {
source: Option<&'a dyn Source<'a, T>>,
}
impl<'a, T> SyncSink<'a, T> {
pub fn new() -> SyncSink<'a, T> {
SyncSink {
source: None,
}
}
}
impl<'a, T> Sink<'a, T> for SyncSink<'a, T> {
fn push(&self, t: T) -> io::Result<()> {
match self.source {
Some(source) => source.push(t),
None => Err(io::Error::new(io::ErrorKind::NotConnected, "no source")),
}
}
fn link(&mut self, source: &dyn Source<T>) -> io::Result<()> {
self.source = Some(source);
Ok(())
}
}
I read the rustlang book chapter about lifetimes but could not really understand what's wrong here. What I'm trying to do is build a basic pipe and filter architecture. A source knows its sink and a sink knows its source, thus I want to store references to the objects. Obviously, there's a lifetime issue here.
I first thought about introducing the lifetime 'a
to say the source/sink shall live as long as the object it is linked to. This does not work. Now I'm thinking I may need a lifetime 'b which outlives 'a and somehow throw that in the mix, but as you can see, this is where I am confused.