Skip to content

Commit

Permalink
Merge pull request #53 from bugadani/compile
Browse files Browse the repository at this point in the history
Reintroduce separate lifetimes for buffer and stream
  • Loading branch information
rmja committed Oct 24, 2023
2 parents 2f71cc9 + c503eb4 commit 5bc9013
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 32 deletions.
27 changes: 13 additions & 14 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ where
/// The response headers are stored in the provided rx_buf, which should be sized to contain at least the response headers.
///
/// The response is returned.
pub async fn send<'buf, B: RequestBody>(
&'buf mut self,
pub async fn send<'req, 'buf, B: RequestBody>(
&'req mut self,
request: Request<'conn, B>,
rx_buf: &'buf mut [u8],
) -> Result<Response<'buf, HttpConnection<'conn, T>>, Error> {
) -> Result<Response<'req, 'buf, HttpConnection<'conn, T>>, Error> {
request.write(self).await?;
Response::read(self, request.method, rx_buf).await
}
Expand Down Expand Up @@ -326,10 +326,10 @@ where
/// The response headers are stored in the provided rx_buf, which should be sized to contain at least the response headers.
///
/// The response is returned.
pub async fn send<'buf>(
&'buf mut self,
pub async fn send<'req, 'buf>(
&'req mut self,
rx_buf: &'buf mut [u8],
) -> Result<Response<'buf, HttpConnection<'conn, C>>, Error> {
) -> Result<Response<'req, 'buf, HttpConnection<'conn, C>>, Error> {
let request = self.request.take().ok_or(Error::AlreadySent)?.build();
request.write(&mut self.conn).await?;
Response::read(&mut self.conn, request.method, rx_buf).await
Expand Down Expand Up @@ -454,11 +454,11 @@ where
/// The response headers are stored in the provided rx_buf, which should be sized to contain at least the response headers.
///
/// The response is returned.
pub async fn send<'req, B: RequestBody>(
pub async fn send<'req, 'buf, B: RequestBody>(
&'req mut self,
mut request: Request<'req, B>,
rx_buf: &'req mut [u8],
) -> Result<Response<'req, HttpConnection<'res, C>>, Error> {
rx_buf: &'buf mut [u8],
) -> Result<Response<'req, 'buf, HttpConnection<'res, C>>, Error> {
request.base_path = Some(self.base_path);
request.write(&mut self.conn).await?;
Response::read(&mut self.conn, request.method, rx_buf).await
Expand Down Expand Up @@ -486,11 +486,10 @@ where
/// The response headers are stored in the provided rx_buf, which should be sized to contain at least the response headers.
///
/// The response is returned.
pub async fn send<'buf>(self, rx_buf: &'buf mut [u8]) -> Result<Response<'buf, HttpConnection<'conn, C>>, Error>
where
'conn: 'req + 'buf,
'req: 'buf,
{
pub async fn send<'buf>(
self,
rx_buf: &'buf mut [u8],
) -> Result<Response<'req, 'buf, HttpConnection<'conn, C>>, Error> {
let conn = self.conn;
let mut request = self.request.build();
request.base_path = Some(self.base_path);
Expand Down
14 changes: 7 additions & 7 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,34 +42,34 @@ impl ReadBuffer<'_> {
}
}

pub struct BufferingReader<'buf, B>
pub struct BufferingReader<'resp, 'buf, B>
where
B: Read,
{
buffer: ReadBuffer<'buf>,
stream: &'buf mut B,
stream: &'resp mut B,
}

impl<'buf, 'conn, B> BufferingReader<'buf, B>
impl<'resp, 'buf, B> BufferingReader<'resp, 'buf, B>
where
B: Read,
{
pub fn new(buffer: &'buf mut [u8], loaded: usize, stream: &'buf mut B) -> Self {
pub fn new(buffer: &'buf mut [u8], loaded: usize, stream: &'resp mut B) -> Self {
Self {
buffer: ReadBuffer::new(buffer, loaded),
stream,
}
}
}

impl<C> ErrorType for BufferingReader<'_, C>
impl<C> ErrorType for BufferingReader<'_, '_, C>
where
C: Read,
{
type Error = ErrorKind;
}

impl<C> Read for BufferingReader<'_, C>
impl<C> Read for BufferingReader<'_, '_, C>
where
C: Read,
{
Expand All @@ -83,7 +83,7 @@ where
}
}

impl<C> BufRead for BufferingReader<'_, HttpConnection<'_, C>>
impl<C> BufRead for BufferingReader<'_, '_, HttpConnection<'_, C>>
where
C: Read + Write,
{
Expand Down
22 changes: 11 additions & 11 deletions src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::Error;
/// Type representing a parsed HTTP response.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Response<'resp, C>
pub struct Response<'resp, 'buf, C>
where
C: Read,
{
Expand All @@ -27,17 +27,17 @@ where
pub transfer_encoding: heapless::Vec<TransferEncoding, 4>,
/// The keep-alive parameters.
pub keep_alive: Option<KeepAlive>,
header_buf: &'resp mut [u8],
header_buf: &'buf mut [u8],
header_len: usize,
raw_body_read: usize,
}

impl<'resp, C> Response<'resp, C>
impl<'resp, 'buf, C> Response<'resp, 'buf, C>
where
C: Read,
{
// Read at least the headers from the connection.
pub async fn read(conn: &'resp mut C, method: Method, header_buf: &'resp mut [u8]) -> Result<Self, Error> {
pub async fn read(conn: &'resp mut C, method: Method, header_buf: &'buf mut [u8]) -> Result<Self, Error> {
let mut header_len = 0;
let mut pos = 0;
while pos < header_buf.len() {
Expand Down Expand Up @@ -135,7 +135,7 @@ where
}

/// Get the response body
pub fn body(self) -> ResponseBody<'resp, C> {
pub fn body(self) -> ResponseBody<'resp, 'buf, C> {
let reader_hint = if self.method == Method::HEAD {
// Head requests does not have a body so we return an empty reader
ReaderHint::Empty
Expand Down Expand Up @@ -179,7 +179,7 @@ impl<'a> Iterator for HeaderIterator<'a> {
/// This type contains the original header buffer provided to `read_headers`,
/// now renamed to `body_buf`, the number of read body bytes that are available
/// in `body_buf`, and a reader to be used for reading the remaining body.
pub struct ResponseBody<'resp, C>
pub struct ResponseBody<'resp, 'buf, C>
where
C: Read,
{
Expand All @@ -188,7 +188,7 @@ where
/// The number of raw bytes read from the body and available in the beginning of `body_buf`.
raw_body_read: usize,
/// The buffer initially provided to read the header.
pub body_buf: &'resp mut [u8],
pub body_buf: &'buf mut [u8],
}

enum ReaderHint {
Expand All @@ -198,11 +198,11 @@ enum ReaderHint {
ToEnd, // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.3 pt. 7: Until end of connection
}

impl<'resp, C> ResponseBody<'resp, C>
impl<'resp, 'buf, C> ResponseBody<'resp, 'buf, C>
where
C: Read,
{
pub fn reader(self) -> BodyReader<BufferingReader<'resp, C>> {
pub fn reader(self) -> BodyReader<BufferingReader<'resp, 'buf, C>> {
let raw_body = BufferingReader::new(self.body_buf, self.raw_body_read, self.conn);

match self.reader_hint {
Expand All @@ -220,7 +220,7 @@ where
}
}

impl<'resp, C> ResponseBody<'resp, C>
impl<'resp, 'buf, C> ResponseBody<'resp, 'buf, C>
where
C: Read,
{
Expand All @@ -231,7 +231,7 @@ where
/// while parsing the http response header would be available for the body reader.
/// For this case, or if the original buffer is not large enough, use
/// [`BodyReader::read_to_end()`] instead from the reader returned by [`ResponseBody::reader()`].
pub async fn read_to_end(self) -> Result<&'resp mut [u8], Error> {
pub async fn read_to_end(self) -> Result<&'buf mut [u8], Error> {
// We can only read responses with Content-Length header to end using the body_buf buffer,
// as any other response would require the body reader to know the entire body.
match self.reader_hint {
Expand Down
12 changes: 12 additions & 0 deletions tests/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,15 @@ async fn echo(req: hyper::Request<Body>) -> Result<hyper::Response<Body>, hyper:
_ => Ok(hyper::Response::new(req.into_body())),
}
}

#[test]
fn compile_tests() {
#[allow(dead_code)]
async fn rx_buffer_lifetime_is_propagated_to_output<'buf>(port: u16, rx_buf: &'buf mut [u8]) -> &'buf mut [u8] {
let mut http = HttpClient::new(&TCP, &LOOPBACK_DNS);
let url = format!("http://127.0.0.1:{}", port);
let mut request = http.request(Method::GET, &url).await.unwrap();
let response = request.send(rx_buf).await.unwrap();
response.body().read_to_end().await.unwrap()
}
}

0 comments on commit 5bc9013

Please sign in to comment.