Closed Wesmania closed 3 years ago
The test included in this PR doesn't have any "tests". The moment I added a test I got compiler errors when running cargo test
. I can try to fix them but I need more context on what is the use case. I know the method you are trying to use is Pin<&mut Self>
but I also need to know where the Pin
came from, was it a Pin<Box>
, Pin<Rc>
, other...?. Are there other kind of receivers that you would need apart from Pin<&mut Self>
I have no idea where the Pin
is coming from, I'll check tokio
's code and try writing some actual tests. I think prototype
was a bad word choice for this PR, it's more of a work-in-progress/sketch.
Do you have a quick snippet of the code you are working with?
Minimal example would be something like this:
use tokio::{io::BufReader, net::TcpStream, io::AsyncRead};
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
pub struct Connection
{
reader: BufReader<OwnedReadHalf>,
writer: OwnedWriteHalf,
}
impl Connection {
pub fn new(stream: TcpStream) -> Self {
let (r, writer) = stream.into_split();
let reader = BufReader::new(r);
Self {reader, writer}
}
}
impl AsyncRead for Connection {
fn poll_read(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
let me = unsafe { self.get_unchecked_mut() };
let reader = unsafe {std::pin::Pin::new_unchecked(&mut me.reader) };
AsyncRead::poll_read(reader, cx, buf)
}
}
Hmm I see. So poll_read
is called somewhere by tokio
, it is not something you call directly? Where do you pass your Connection
to tokio for it to use?
I don't pass it anywhere right now, since until now I just called methods that used inner streams. Simplest use would be calling connection.read
using AsyncReadExt trait.
Like so:
use tokio::{io::BufReader, net::TcpStream, io::AsyncRead, net::TcpListener, io::AsyncReadExt};
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
pub async fn connections() -> () {
let listener = TcpListener::bind("localhost").await.unwrap();
loop {
match listener.accept().await {
Err(_) => (),
Ok((socket, _addr)) => {
let mut foo = Connection::new(socket);
let mut num = [0; 10];
foo.read(&mut num);
}
}
}
}
The important bits for Tokio seems to be in src/io/util/read.rs
.
That was extremely helpful, thanks!
This is a bit trickier than the existing "self types" in faux
because Pin
is never just Pin<T>
in the way that Rc<T>
is. Pin always wraps some "pointer" type (i.e., Pin<&mut T>
). I am hopeful to have a working implementation for this soon that I will put as a commit on top of your branch and merge it as as soon as I get some time. Arbitrary self types is the most complex part of faux
, or at least the part where I wrote the messiest code so it's taking me a bit to unravel it 😁
Thanks a lot @Wesmania!
Happy to be helpful :) I had a hunch that Pin tends to wrap multiple things, that bit I wrote just happened to work in this case I guess.
I finally got it to the point where all tests pass again. This should not work for pinned &Self
, &mut Self
, Rc<Self>
, Arc<Self>
, and Box<Self
. I will make a release after I update the docs.
Fixes #29.
Signed-off-by: Igor Kotrasinski i.kotrasinsk@gmail.com