From b1128cd461ada0d52d8987407cca98530f2067b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 21 Oct 2023 21:01:07 +0200 Subject: [PATCH] Clean up internals --- src/client.rs | 11 ++++--- src/reader.rs | 29 ++++++++-------- src/response.rs | 88 ++++++++++++++++++++++--------------------------- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/src/client.rs b/src/client.rs index 751ab4c..7acaa86 100644 --- a/src/client.rs +++ b/src/client.rs @@ -207,7 +207,7 @@ where &'buf mut self, request: Request<'conn, B>, rx_buf: &'buf mut [u8], - ) -> Result, Error> { + ) -> Result>, Error> { request.write(self).await?; Response::read(self, request.method, rx_buf).await } @@ -299,7 +299,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, rx_buf: &'buf mut [u8]) -> Result, Error> { + pub async fn send<'buf>( + &'buf mut self, + rx_buf: &'buf mut [u8], + ) -> Result>, 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 @@ -428,7 +431,7 @@ where &'req mut self, mut request: Request<'req, B>, rx_buf: &'req mut [u8], - ) -> Result, Error> { + ) -> Result>, Error> { request.base_path = Some(self.base_path); request.write(&mut self.conn).await?; Response::read(&mut self.conn, request.method, rx_buf).await @@ -456,7 +459,7 @@ 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, Error> + pub async fn send<'buf>(self, rx_buf: &'buf mut [u8]) -> Result>, Error> where 'conn: 'req + 'buf, 'req: 'buf, diff --git a/src/reader.rs b/src/reader.rs index 7cd8adb..62cfb83 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -1,9 +1,6 @@ -use embedded_io::{ErrorKind, ErrorType}; +use embedded_io::{Error, ErrorKind, ErrorType}; use embedded_io_async::{BufRead, Read, Write}; -#[cfg(feature = "embedded-tls")] -use embedded_io::Error; - use crate::client::HttpConnection; struct ReadBuffer<'buf> { @@ -45,19 +42,19 @@ impl ReadBuffer<'_> { } } -pub struct BufferingReader<'buf, 'conn, B> +pub struct BufferingReader<'buf, B> where - B: Read + Write, + B: Read, { buffer: ReadBuffer<'buf>, - stream: &'buf mut HttpConnection<'conn, B>, + stream: &'buf mut B, } -impl<'buf, 'conn, B> BufferingReader<'buf, 'conn, B> +impl<'buf, 'conn, B> BufferingReader<'buf, B> where - B: Read + Write, + B: Read, { - pub fn new(buffer: &'buf mut [u8], loaded: usize, stream: &'buf mut HttpConnection<'conn, B>) -> Self { + pub fn new(buffer: &'buf mut [u8], loaded: usize, stream: &'buf mut B) -> Self { Self { buffer: ReadBuffer::new(buffer, loaded), stream, @@ -65,16 +62,16 @@ where } } -impl ErrorType for BufferingReader<'_, '_, C> +impl ErrorType for BufferingReader<'_, C> where - C: Read + Write, + C: Read, { type Error = ErrorKind; } -impl Read for BufferingReader<'_, '_, C> +impl Read for BufferingReader<'_, C> where - C: Read + Write, + C: Read, { async fn read(&mut self, buf: &mut [u8]) -> Result { if !self.buffer.is_empty() { @@ -82,11 +79,11 @@ where return Ok(amt); } - self.stream.read(buf).await + self.stream.read(buf).await.map_err(|e| e.kind()) } } -impl BufRead for BufferingReader<'_, '_, C> +impl BufRead for BufferingReader<'_, HttpConnection<'_, C>> where C: Read + Write, { diff --git a/src/response.rs b/src/response.rs index c52dbf6..522b416 100644 --- a/src/response.rs +++ b/src/response.rs @@ -2,18 +2,17 @@ use embedded_io::{Error as _, ErrorType}; use embedded_io_async::{BufRead, Read, Write}; use heapless::Vec; -use crate::client::HttpConnection; use crate::headers::{ContentType, KeepAlive, TransferEncoding}; use crate::reader::BufferingReader; use crate::request::Method; use crate::Error; /// Type representing a parsed HTTP response. -pub struct Response<'buf, 'conn, C> +pub struct Response<'buf, C> where - C: Read + Write, + C: Read, { - conn: &'buf mut HttpConnection<'conn, C>, + conn: &'buf mut C, /// The method used to create the response. method: Method, /// The HTTP response status code. @@ -32,7 +31,7 @@ where } #[cfg(feature = "defmt")] -impl defmt::Format for Response<'_, '_, C> +impl defmt::Format for Response<'_, C> where C: Read + Write, { @@ -53,7 +52,7 @@ where } } -impl core::fmt::Debug for Response<'_, '_, C> +impl core::fmt::Debug for Response<'_, C> where C: Read + Write, { @@ -72,16 +71,12 @@ where } } -impl<'buf, 'conn, C> Response<'buf, 'conn, C> +impl<'buf, C> Response<'buf, C> where - C: Read + Write, + C: Read, { // Read at least the headers from the connection. - pub async fn read( - conn: &'buf mut HttpConnection<'conn, C>, - method: Method, - header_buf: &'buf mut [u8], - ) -> Result, Error> { + pub async fn read(conn: &'buf mut C, method: Method, header_buf: &'buf mut [u8]) -> Result { let mut header_len = 0; let mut pos = 0; while pos < header_buf.len() { @@ -179,7 +174,7 @@ where } /// Get the response body - pub fn body(self) -> ResponseBody<'buf, 'conn, C> { + pub fn body(self) -> ResponseBody<'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 @@ -223,11 +218,11 @@ 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<'buf, 'conn, C> +pub struct ResponseBody<'buf, C> where - C: Read + Write, + C: Read, { - conn: &'buf mut HttpConnection<'conn, C>, + conn: &'buf mut C, reader_hint: ReaderHint, /// The number of raw bytes read from the body and available in the beginning of `body_buf`. raw_body_read: usize, @@ -242,11 +237,11 @@ enum ReaderHint { ToEnd, // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.3 pt. 7: Until end of connection } -impl<'buf, 'conn, C> ResponseBody<'buf, 'conn, C> +impl<'buf, C> ResponseBody<'buf, C> where - C: Read + Write, + C: Read, { - pub fn reader(self) -> BodyReader> { + pub fn reader(self) -> BodyReader> { let raw_body = BufferingReader::new(self.body_buf, self.raw_body_read, self.conn); match self.reader_hint { @@ -264,9 +259,9 @@ where } } -impl<'buf, 'conn, C> ResponseBody<'buf, 'conn, C> +impl<'buf, C> ResponseBody<'buf, C> where - C: Read + Write, + C: Read, { /// Read the entire body into the buffer originally provided [`Response::read()`]. /// This requires that this original buffer is large enough to contain the entire body. @@ -326,7 +321,7 @@ pub enum BodyReader { impl BodyReader where - B: BufRead + Read, + B: Read, { /// Read the entire body pub async fn read_to_end(&mut self, buf: &mut [u8]) -> Result { @@ -360,14 +355,13 @@ where async fn discard(&mut self) -> Result { let mut body_len = 0; + let mut buf = [0; 128]; loop { - let buf = self.fill_buf().await?; - if buf.is_empty() { + let buf = self.read(&mut buf).await?; + if buf == 0 { break; } - let buf_len = buf.len(); - body_len += buf_len; - self.consume(buf_len); + body_len += buf; } Ok(body_len) @@ -380,7 +374,7 @@ impl ErrorType for BodyReader { impl Read for BodyReader where - B: BufRead + Read, + B: Read, { async fn read(&mut self, buf: &mut [u8]) -> Result { match self { @@ -427,7 +421,7 @@ impl ErrorType for FixedLengthBodyReader { impl Read for FixedLengthBodyReader where - C: BufRead + Read, + C: Read, { async fn read(&mut self, buf: &mut [u8]) -> Result { if self.remaining == 0 { @@ -506,31 +500,29 @@ pub struct ChunkedBodyReader { impl ChunkedBodyReader where - C: BufRead + Read, + C: Read, { async fn read_next_chunk_length(&mut self) -> Result<(), Error> { let mut header_buf = [0; 8 + 2]; // 32 bit hex + \r + \n let mut total_read = 0; 'read_size: loop { - let buf = self.raw_body.fill_buf().await.map_err(|e| e.kind())?; - for (i, byte) in buf.iter().enumerate() { - if *byte != b'\n' { - header_buf[total_read] = *byte; - total_read += 1; - - if total_read == header_buf.len() { - self.raw_body.consume(i + 1); - return Err(Error::Codec); - } - } else { - self.raw_body.consume(i + 1); - break 'read_size; + let mut byte = 0; + self.raw_body + .read_exact(core::slice::from_mut(&mut byte)) + .await + .map_err(|e| Error::from(e).kind())?; + + if byte != b'\n' { + header_buf[total_read] = byte; + total_read += 1; + + if total_read == header_buf.len() { + return Err(Error::Codec); } + } else { + break 'read_size; } - - let consumed = buf.len(); - self.raw_body.consume(consumed); } if header_buf[total_read - 1] != b'\r' { @@ -595,7 +587,7 @@ impl ErrorType for ChunkedBodyReader { impl Read for ChunkedBodyReader where - C: BufRead + Read, + C: Read, { async fn read(&mut self, buf: &mut [u8]) -> Result { let remaining = self.handle_chunk_boundary().await?;