I'm trying to implement implement a trait that requires splitting a Session that can read/write into a Reader/Writer structs. I plan using a Mutex for synchronization.
The issue is with lifetimes which I can't get to do right. I tried multiple options (with Rc, Option, Weak for referencing the main struct) and nothing worked so it's about something I just don't understand:
Here is the simplified code, and below the error I get.
What's wrong and what should I change if at all possible to do?
// Wrapper of session
pub struct SessionWrapper<'a> {
session: Mutex<NoopRawMutex, Session<'a, TcpSocket<'a>>>,
}
impl<'a,'s> SessionWrapper<'s>
where
's: 'a
{
pub fn new(session: Session<'s, TcpSocket<'s>>) -> Self {
Self {
session: Mutex::new(session)
}
}
}
// Reader
pub struct SessionReader<'a> {
session: &'a Mutex<NoopRawMutex, Session<'a, TcpSocket<'a>>>
}
impl<'a> embedded_io_async::ErrorType for SessionReader<'a> {
type Error = TlsError;
}
impl<'a> embedded_io_async::Read for SessionReader<'a> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut session = self.session.lock().await;
session.read(buf).await
}
}
pub struct SessionWriter
{
}
impl embedded_io_async::ErrorType for SessionWriter
{
type Error = TlsError;
}
impl embedded_io_async::Write for SessionWriter
{
// async fn write(&mut self, _buf: &[u8]) -> Result<usize, Self::Error> {
// Ok(0)
// }
//
// async fn flush(&mut self) -> Result<(), Self::Error> {
// Ok(())
// }
}
// Implement picoserve Socket on SessionWrapper
impl <'s> picoserve::io::Socket for SessionWrapper<'s>{
type Error = TlsError;
type ReadHalf<'a> = SessionReader<'a> where 's: 'a;
type WriteHalf<'a> = SessionWriter where 's : 'a;
fn split(&mut self) -> (Self::ReadHalf<'_>, Self::WriteHalf<'_>) {
let session = &self.session;
(
SessionReader{
session
},
SessionWriter {},
)
}
async fn shutdown<Timer: picoserve::Timer>(
mut self,
_timeouts: &picoserve::Timeouts<Timer::Duration>,
_timer: &mut Timer,
) -> Result<(), picoserve::Error<Self::Error>> {
Ok(())
}
}`
Error
error: lifetime may not live long enough
--> src/framework/web_config.rs:389:9
|
382 | impl <'s> picoserve::io::Socket for SessionWrapper<'s>{
| -- lifetime `'s` defined here
...
387 | fn split(&mut self) -> (Self::ReadHalf<'_>, Self::WriteHalf<'_>) {
| - let's call the lifetime of this reference `'1`
388 | let session = &self.session; // Mutably borrow the session inside the Option
389 | / (
390 | | SessionReader{
391 | | session
392 | | },
393 | | SessionWriter {},
394 | | )
| |_________^ method was supposed to return data with lifetime `'s` but it is returning data with lifetime `'1`
|
= note: requirement occurs because of the type `SessionReader<'_>`, which makes the generic argument `'_` invariant
= note: the struct `SessionReader<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance