Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BufRead::fill_buf #176

Merged
3 commits merged into from
Sep 11, 2019
Merged

Add BufRead::fill_buf #176

3 commits merged into from
Sep 11, 2019

Conversation

tirr-c
Copy link
Contributor

@tirr-c tirr-c commented Sep 10, 2019

Tracking issue: #131. Docs from std.

Note that there is a use of unsafe in fill_buf.rs that transmutes the lifetime of output buffer.

fn from(reader: &'a mut R) -> Self {
Self { reader }
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given there is only a single creator of this future, is this From impl necessary? If it is, could we perhaps add a comment to explain why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to make reader field private, but yeah, it could be an associated function, or just make reader pub(crate).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tirr-c This is not a big issue, but given a choice I'd prefer a pub(crate) field and a function in order to not leak any unintended APIs publicly. This impl is currently public in the sense that the user could do .into() to convert a buffer into the future.

Copy link
Contributor

@yoshuawuyts yoshuawuyts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, but I'm not an expert on pinning so definitely want to get at least one more review in before merging. Thanks so much for putting in the work!

@yoshuawuyts yoshuawuyts requested a review from a user September 10, 2019 16:08
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me, and I only have minor nits :)

fn from(reader: &'a mut R) -> Self {
Self { reader }
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tirr-c This is not a big issue, but given a choice I'd prefer a pub(crate) field and a function in order to not leak any unintended APIs publicly. This impl is currently public in the sense that the user could do .into() to convert a buffer into the future.

// This is safe because:
// 1. The buffer is valid for the lifetime of the reader.
// 2. Output is unrelated to the wrapper (Self).
result.map_ok(|buf| unsafe { std::mem::transmute::<_, &'a [u8]>(buf) })
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm always a bit anxious about mixing type inference and transmute, so could you perhaps make types more explicit like this?

Suggested change
result.map_ok(|buf| unsafe { std::mem::transmute::<_, &'a [u8]>(buf) })
result.map_ok(|buf| unsafe { std::mem::transmute::<&'_ [u8], &'a [u8]>(buf) })

@ghost
Copy link

ghost commented Sep 11, 2019

A logical follow-up now would be to add the consume method. I'm okay with either adding it in this PR or in a new PR.

@yoshuawuyts yoshuawuyts mentioned this pull request Sep 11, 2019
@tirr-c
Copy link
Contributor Author

tirr-c commented Sep 11, 2019

@stjepang Review addressed!

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@ghost
Copy link

ghost commented Sep 11, 2019

bors r+

bors bot added a commit that referenced this pull request Sep 11, 2019
176: Add BufRead::fill_buf r=stjepang a=tirr-c

Tracking issue: #131. Docs from `std`.

**Note** that there is a use of `unsafe` in `fill_buf.rs` that transmutes the lifetime of output buffer.

Co-authored-by: Wonwoo Choi <chwo9843@gmail.com>
@bors
Copy link
Contributor

bors bot commented Sep 11, 2019

Build failed

  • continuous-integration/travis-ci/push

@ghost ghost merged commit 06f2569 into async-rs:master Sep 11, 2019
@taiki-e
Copy link
Contributor

taiki-e commented May 3, 2020

This implementation is unsound (this already reverted in edfa235 without explanation, but I leave this comment to prevent someone from accidentally using this implementation, like #763).

Specifically, this implementation allows you to write code like this (this is because FillBufFuture::poll is changing the lifetime of the output):

playground

let mut r = R([0]);
let mut r = FillBufFuture::new(&mut r);
let mut r = Pin::new(&mut r);
let w = noop_waker();
let mut cx = Context::from_waker(&w);

let x = r.as_mut().poll(&mut cx);
println!("{:?}", x); // Ready(Ok([1]))
let _y = r.as_mut().poll(&mut cx);
println!("{:?}", x); // Ready(Ok([2]))

struct R([u8; 1]);
impl AsyncBufRead for R {
    fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
        self.0[0] += 1;
        Poll::Ready(Ok(&self.into_ref().get_ref().0))
    }
    fn consume(self: Pin<&mut Self>, _: usize) {
        unimplemented!()
    }
}

EDIT: My previous comments seem incorrect... Probably this needs to make reader Option and drop the reader if reader returns Ready.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants