#![cfg_attr(not(test), no_std)]
#![doc = include_str!("../README.md")]
#![allow(async_fn_in_trait)]
use core::{num::ParseIntError, str::Utf8Error};
use embedded_io_async::ReadExactError;
mod fmt;
mod body_writer;
pub mod client;
pub mod headers;
mod reader;
pub mod request;
pub mod response;
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
Dns,
Network(embedded_io::ErrorKind),
Codec,
InvalidUrl(nourl::Error),
#[cfg(feature = "embedded-tls")]
Tls(embedded_tls::TlsError),
#[cfg(feature = "esp-mbedtls")]
Tls(esp_mbedtls::TlsError),
BufferTooSmall,
AlreadySent,
IncorrectBodyWritten,
ConnectionAborted,
}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(self, f)
}
}
impl core::error::Error for Error {}
impl embedded_io::Error for Error {
fn kind(&self) -> embedded_io::ErrorKind {
match self {
Error::Network(kind) => *kind,
Error::ConnectionAborted => embedded_io::ErrorKind::ConnectionAborted,
_ => embedded_io::ErrorKind::Other,
}
}
}
impl From<embedded_io::ErrorKind> for Error {
fn from(e: embedded_io::ErrorKind) -> Error {
Error::Network(e)
}
}
impl<E: embedded_io::Error> From<ReadExactError<E>> for Error {
fn from(value: ReadExactError<E>) -> Self {
match value {
ReadExactError::UnexpectedEof => Error::ConnectionAborted,
ReadExactError::Other(e) => Error::Network(e.kind()),
}
}
}
#[cfg(feature = "embedded-tls")]
impl From<embedded_tls::TlsError> for Error {
fn from(e: embedded_tls::TlsError) -> Error {
Error::Tls(e)
}
}
#[cfg(feature = "esp-mbedtls")]
pub use esp_mbedtls::{Certificates, TlsReference, TlsVersion, X509};
#[cfg(feature = "esp-mbedtls")]
impl From<esp_mbedtls::TlsError> for Error {
fn from(e: esp_mbedtls::TlsError) -> Error {
Error::Tls(e)
}
}
impl From<ParseIntError> for Error {
fn from(_: ParseIntError) -> Error {
Error::Codec
}
}
impl From<Utf8Error> for Error {
fn from(_: Utf8Error) -> Error {
Error::Codec
}
}
impl From<nourl::Error> for Error {
fn from(e: nourl::Error) -> Self {
Error::InvalidUrl(e)
}
}
pub trait TryBufRead: embedded_io_async::Read {
async fn try_fill_buf(&mut self) -> Option<Result<&[u8], Self::Error>> {
None
}
fn try_consume(&mut self, _amt: usize) {}
}
impl<C> TryBufRead for crate::client::HttpConnection<'_, C>
where
C: embedded_io_async::Read + embedded_io_async::Write,
{
async fn try_fill_buf(&mut self) -> Option<Result<&[u8], Self::Error>> {
#[cfg(feature = "embedded-tls")]
if let Self::Tls(ref mut tls) = *self {
use embedded_io_async::{BufRead, Error};
return Some(tls.fill_buf().await.map_err(|e| e.kind()));
}
None
}
fn try_consume(&mut self, amt: usize) {
#[cfg(feature = "embedded-tls")]
if let Self::Tls(tls) = self {
use embedded_io_async::BufRead;
tls.consume(amt);
}
#[cfg(not(feature = "embedded-tls"))]
{
_ = amt;
}
}
}