From c49a502d2ca4a3ccf1c689aa3ca352f69ed9401a Mon Sep 17 00:00:00 2001 From: kbleeke Date: Sat, 30 Sep 2023 11:09:35 +0200 Subject: [PATCH] update embedded-io to 0.5 --- Cargo.toml | 20 +++++++---- src/client.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++---- src/concat.rs | 5 +-- src/lib.rs | 14 +++++++- src/request.rs | 51 +++++++++++++++------------ src/response.rs | 9 ++--- tests/client.rs | 2 +- tests/request.rs | 2 +- 8 files changed, 152 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cd0846b..8571683 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,10 @@ keywords = ["embedded", "async", "http", "no_std"] exclude = [".github"] [dependencies] -buffered-io = { version = "0.1.0", features = ["async"] } -embedded-io = { version = "0.4.0", features = ["async"] } -embedded-nal-async = "0.4.0" +buffered-io = { version = "0.3.0", features = ["async"] } +embedded-io = { version = "0.5.0" } +embedded-io-async = { version = "0.5.0" } +embedded-nal-async = "0.5.0" httparse = { version = "1.8.0", default-features = false } heapless = "0.7" hex = { version = "0.4", default-features = false } @@ -23,7 +24,7 @@ base64 = { version = "0.21.0", default-features = false } rand_core = { version = "0.6", default-features = true } log = { version = "0.4", optional = true } defmt = { version = "0.3", optional = true } -embedded-tls = { version = "0.14", default-features = false, features = [ +embedded-tls = { version = "0.15", default-features = false, features = [ "async", ], optional = true } rand_chacha = { version = "0.3", default-features = false } @@ -34,7 +35,8 @@ hyper = { version = "0.14.23", features = ["full"] } tokio = { version = "1.21.2", features = ["full"] } tokio-rustls = { version = "0.23.4" } futures-util = { version = "0.3" } -embedded-io = { version = "0.4", features = ["async", "tokio"] } +embedded-io-async = { version = "0.5", features = ["std"] } +embedded-io-adapters = { version = "0.5", features = ["std", "tokio-1"] } rustls-pemfile = "1.0" env_logger = "0.10" log = "0.4" @@ -43,4 +45,10 @@ rand = "0.8" [features] default = ["embedded-tls"] alloc = ["embedded-tls?/alloc"] -defmt = ["dep:defmt", "embedded-io/defmt", "embedded-tls?/defmt", "nourl/defmt"] +defmt = [ + "dep:defmt", + "embedded-io/defmt-03", + "embedded-io-async/defmt-03", + "embedded-tls?/defmt", + "nourl/defmt", +] diff --git a/src/client.rs b/src/client.rs index 626c2d9..1b638b2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,8 +5,9 @@ use crate::request::*; use crate::response::*; use crate::Error; use buffered_io::asynch::BufferedWrite; -use embedded_io::asynch::{Read, Write}; use embedded_io::Error as _; +use embedded_io::ErrorType; +use embedded_io_async::{Read, Write}; use embedded_nal_async::{Dns, SocketAddr, TcpConnect}; use nourl::{Url, UrlScheme}; @@ -184,7 +185,7 @@ where } } -impl embedded_io::Io for HttpConnection<'_, T> +impl ErrorType for HttpConnection<'_, T> where T: Read + Write, { @@ -242,9 +243,12 @@ where /// Turn the request into a buffered request /// /// This is most likely only relevant for non-tls endpoints, as `embedded-tls` buffers internally. - pub fn into_buffered<'buf>(self, tx_buf: &'buf mut [u8]) -> HttpRequestHandle<'m, BufferedWrite<'buf, C>, B> { + pub fn into_buffered<'buf>( + self, + tx_buf: &'buf mut [u8], + ) -> HttpRequestHandle<'m, BufferedWrite<'buf, buffered_io_adapter::ConnErrorAdapter>, B> { HttpRequestHandle { - conn: BufferedWrite::new(self.conn, tx_buf), + conn: BufferedWrite::new(buffered_io_adapter::ConnErrorAdapter(self.conn), tx_buf), request: self.request, } } @@ -324,9 +328,12 @@ where /// Turn the resource into a buffered resource /// /// This is most likely only relevant for non-tls endpoints, as `embedded-tls` buffers internally. - pub fn into_buffered<'buf>(self, tx_buf: &'buf mut [u8]) -> HttpResource<'res, BufferedWrite<'buf, C>> { + pub fn into_buffered<'buf>( + self, + tx_buf: &'buf mut [u8], + ) -> HttpResource<'res, BufferedWrite<'buf, buffered_io_adapter::ConnErrorAdapter>> { HttpResource { - conn: BufferedWrite::new(self.conn, tx_buf), + conn: BufferedWrite::new(buffered_io_adapter::ConnErrorAdapter(self.conn), tx_buf), host: self.host, base_path: self.base_path, } @@ -478,3 +485,76 @@ where self.request.build() } } + +mod buffered_io_adapter { + use embedded_io::{Error as _, ErrorType, ReadExactError, WriteAllError}; + use embedded_io_async::{Read, Write}; + + pub struct Error(embedded_io::ErrorKind); + + impl core::fmt::Debug for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.0.fmt(f) + } + } + + impl embedded_io_async::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + self.0 + } + } + + impl From> for Error + where + T: embedded_io::Error, + { + fn from(value: WriteAllError) -> Self { + match value { + WriteAllError::WriteZero => Self(embedded_io::ErrorKind::Other), + WriteAllError::Other(e) => Self(e.kind()), + } + } + } + + pub struct ConnErrorAdapter(pub C); + + impl ErrorType for ConnErrorAdapter { + type Error = Error; + } + + impl Write for ConnErrorAdapter + where + C: Write, + { + async fn write(&mut self, buf: &[u8]) -> Result { + self.0.write(buf).await.map_err(|e| Error(e.kind())) + } + + async fn flush(&mut self) -> Result<(), Self::Error> { + self.0.flush().await.map_err(|e| Error(e.kind())) + } + + async fn write_all(&mut self, buf: &[u8]) -> Result<(), embedded_io::WriteAllError> { + self.0.write_all(buf).await.map_err(|e| match e { + WriteAllError::WriteZero => WriteAllError::WriteZero, + WriteAllError::Other(e) => WriteAllError::Other(Error(e.kind())), + }) + } + } + + impl Read for ConnErrorAdapter + where + C: Read, + { + async fn read(&mut self, buf: &mut [u8]) -> Result { + self.0.read(buf).await.map_err(|e| Error(e.kind())) + } + + async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError> { + self.0.read_exact(buf).await.map_err(|e| match e { + ReadExactError::UnexpectedEof => ReadExactError::UnexpectedEof, + ReadExactError::Other(e) => ReadExactError::Other(Error(e.kind())), + }) + } + } +} diff --git a/src/concat.rs b/src/concat.rs index 1e75b59..0d0853f 100644 --- a/src/concat.rs +++ b/src/concat.rs @@ -1,4 +1,5 @@ -use embedded_io::{asynch::Read, ErrorKind, Io}; +use embedded_io::{ErrorKind, ErrorType}; +use embedded_io_async::Read; pub struct ConcatReader where @@ -59,7 +60,7 @@ where } } -impl Io for ConcatReader +impl ErrorType for ConcatReader where A: Read, B: Read, diff --git a/src/lib.rs b/src/lib.rs index 6a4ee2c..ba49b65 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ #![doc = include_str!("../README.md")] use core::{num::ParseIntError, str::Utf8Error}; -use embedded_io::asynch::ReadExactError; +use embedded_io_async::{ReadExactError, WriteAllError}; mod fmt; @@ -61,6 +61,18 @@ impl From> for Error { } } +impl From> for Error +where + E: embedded_io::Error, +{ + fn from(value: WriteAllError) -> Self { + match value { + WriteAllError::WriteZero => Error::Network(embedded_io::ErrorKind::Other), + WriteAllError::Other(e) => Error::Network(e.kind()), + } + } +} + #[cfg(feature = "embedded-tls")] impl From for Error { fn from(e: embedded_tls::TlsError) -> Error { diff --git a/src/request.rs b/src/request.rs index 96b9524..35516bc 100644 --- a/src/request.rs +++ b/src/request.rs @@ -3,8 +3,8 @@ use crate::headers::ContentType; use crate::Error; use core::fmt::Write as _; use core::mem::size_of; -use embedded_io::asynch::Write; -use embedded_io::{Error as _, Io}; +use embedded_io::{Error as _, ErrorType}; +use embedded_io_async::{Write, WriteAllError}; use heapless::String; /// A read only HTTP request type @@ -169,7 +169,7 @@ where Some(len) => { trace!("Writing not-chunked body"); let mut writer = FixedBodyWriter(c, 0); - body.write(&mut writer).await.map_err(|e| e.kind())?; + body.write(&mut writer).await?; if writer.1 != len { return Err(Error::IncorrectBodyWritten); @@ -178,7 +178,7 @@ where None => { trace!("Writing chunked body"); let mut writer = ChunkedBodyWriter(c, 0); - body.write(&mut writer).await.map_err(|e| e.kind())?; + body.write(&mut writer).await?; write_str(c, "0\r\n\r\n").await?; } @@ -273,7 +273,7 @@ impl Method { } async fn write_str(c: &mut C, data: &str) -> Result<(), Error> { - c.write_all(data.as_bytes()).await.map_err(|e| e.kind())?; + c.write_all(data.as_bytes()).await?; Ok(()) } @@ -297,7 +297,7 @@ pub trait RequestBody { } /// Write the body to the provided writer - async fn write(&self, writer: &mut W) -> Result<(), W::Error>; + async fn write(&self, writer: &mut W) -> Result<(), WriteAllError>; } impl RequestBody for () { @@ -305,7 +305,7 @@ impl RequestBody for () { None } - async fn write(&self, _writer: &mut W) -> Result<(), W::Error> { + async fn write(&self, _writer: &mut W) -> Result<(), WriteAllError> { Ok(()) } } @@ -315,7 +315,7 @@ impl RequestBody for &[u8] { Some(<[u8]>::len(self)) } - async fn write(&self, writer: &mut W) -> Result<(), W::Error> { + async fn write(&self, writer: &mut W) -> Result<(), WriteAllError> { writer.write_all(self).await } } @@ -328,7 +328,7 @@ where self.as_ref().map(|inner| inner.len()).unwrap_or_default() } - async fn write(&self, writer: &mut W) -> Result<(), W::Error> { + async fn write(&self, writer: &mut W) -> Result<(), WriteAllError> { if let Some(inner) = self.as_ref() { inner.write(writer).await } else { @@ -339,7 +339,7 @@ where pub struct FixedBodyWriter<'a, C: Write>(&'a mut C, usize); -impl Io for FixedBodyWriter<'_, C> +impl ErrorType for FixedBodyWriter<'_, C> where C: Write, { @@ -356,7 +356,7 @@ where Ok(written) } - async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + async fn write_all(&mut self, buf: &[u8]) -> Result<(), WriteAllError> { self.0.write_all(buf).await?; self.1 += buf.len(); Ok(()) @@ -369,11 +369,18 @@ where pub struct ChunkedBodyWriter<'a, C: Write>(&'a mut C, usize); -impl Io for ChunkedBodyWriter<'_, C> +impl ErrorType for ChunkedBodyWriter<'_, C> where C: Write, { - type Error = C::Error; + type Error = embedded_io::ErrorKind; +} + +fn to_errorkind(e: WriteAllError) -> embedded_io::ErrorKind { + match e { + WriteAllError::WriteZero => embedded_io::ErrorKind::Other, + WriteAllError::Other(e) => e.kind(), + } } impl Write for ChunkedBodyWriter<'_, C> @@ -381,31 +388,31 @@ where C: Write, { async fn write(&mut self, buf: &[u8]) -> Result { - self.write_all(buf).await?; + self.write_all(buf).await.map_err(to_errorkind)?; Ok(buf.len()) } - async fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + async fn write_all(&mut self, buf: &[u8]) -> Result<(), WriteAllError> { // Write chunk header let len = buf.len(); let mut hex = [0; 2 * size_of::()]; hex::encode_to_slice(len.to_be_bytes(), &mut hex).unwrap(); let leading_zeros = hex.iter().position(|x| *x != b'0').unwrap_or_default(); let (_, hex) = hex.split_at(leading_zeros); - self.0.write_all(hex).await?; - self.0.write_all(b"\r\n").await?; + self.0.write_all(hex).await.map_err(to_errorkind)?; + self.0.write_all(b"\r\n").await.map_err(to_errorkind)?; // Write chunk - self.0.write_all(buf).await?; + self.0.write_all(buf).await.map_err(to_errorkind)?; self.1 += len; // Write newline - self.0.write_all(b"\r\n").await?; + self.0.write_all(b"\r\n").await.map_err(to_errorkind)?; Ok(()) } async fn flush(&mut self) -> Result<(), Self::Error> { - self.0.flush().await + self.0.flush().await.map_err(|e| e.kind()) } } @@ -415,7 +422,7 @@ mod tests { #[tokio::test] async fn basic_auth() { - let mut buffer = Vec::new(); + let mut buffer: Vec = Vec::new(); Request::new(Method::GET, "/") .basic_auth("username", "password") .build() @@ -462,7 +469,7 @@ mod tests { None // Unknown length: triggers chunked body } - async fn write(&self, writer: &mut W) -> Result<(), W::Error> { + async fn write(&self, writer: &mut W) -> Result<(), WriteAllError> { writer.write_all(self.0).await } } diff --git a/src/response.rs b/src/response.rs index 45683b0..5bd4736 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,4 +1,5 @@ -use embedded_io::{asynch::Read, Error as _, Io}; +use embedded_io::{Error as _, ErrorType}; +use embedded_io_async::Read; use heapless::Vec; use crate::concat::ConcatReader; @@ -333,7 +334,7 @@ where } } -impl embedded_io::Io for BodyReader +impl ErrorType for BodyReader where B: Read, { @@ -360,7 +361,7 @@ pub struct FixedLengthBodyReader { remaining: usize, } -impl Io for FixedLengthBodyReader { +impl ErrorType for FixedLengthBodyReader { type Error = Error; } @@ -403,7 +404,7 @@ impl ChunkedBodyReader { } } -impl Io for ChunkedBodyReader { +impl ErrorType for ChunkedBodyReader { type Error = Error; } diff --git a/tests/client.rs b/tests/client.rs index 90c0d28..11fc8b5 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -1,7 +1,7 @@ #![feature(async_fn_in_trait)] #![feature(impl_trait_projections)] #![allow(incomplete_features)] -use embedded_io::adapters::FromTokio; +use embedded_io_adapters::tokio_1::FromTokio; use embedded_nal_async::{AddrType, IpAddr, Ipv4Addr}; use hyper::server::conn::Http; use hyper::service::{make_service_fn, service_fn}; diff --git a/tests/request.rs b/tests/request.rs index 8faf4fe..5c43e21 100644 --- a/tests/request.rs +++ b/tests/request.rs @@ -1,4 +1,4 @@ -use embedded_io::adapters::FromTokio; +use embedded_io_adapters::tokio_1::FromTokio; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Server}; use reqwless::request::{Method, RequestBuilder};