Skip to content

Commit

Permalink
4
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Aug 21, 2024
1 parent 8351cd4 commit 73c5acd
Show file tree
Hide file tree
Showing 27 changed files with 270 additions and 141 deletions.
10 changes: 9 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions crates/b-x/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "b-x"
version = "1.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/bearcove/loona"
documentation = "https://docs.rs/b-x"
readme = "README.md"
description = """
The stupidest boxed error ever
"""
rust-version = "1.75.0"

[dependencies]

[features]
default = []
9 changes: 9 additions & 0 deletions crates/b-x/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# b-x

b-x provides the stupidest boxed error ever.

When you don't want `eyre`, you don't want `thiserror`, you don't want `anyhow`,
you want much, much less. Something that just implements `std::error::Error`.

It's not even Send. You have to call `.bx()` on results and/or errors via extension
traits. It's so stupid.
97 changes: 97 additions & 0 deletions crates/b-x/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::{error::Error as StdError, fmt};

/// The stupidest box error ever. It's not even Send.
///
/// It has `From` implementations for some libstd error types,
/// you can derive `From<E>` for your own error types
/// with [impl_from!]
pub struct BX(Box<dyn StdError>);

/// A type alias where `E` defaults to `BX`.
pub type Result<T, E = BX> = std::result::Result<T, E>;

impl BX {
/// Create a new `BX` from an `E`.
pub fn from_err(e: impl StdError + 'static) -> Self {
Self(e.into())
}

/// Create a new `BX` from a boxed `E`.
pub fn from_boxed(e: Box<dyn StdError + 'static>) -> Self {
Self(e)
}
}

pub fn box_error(e: impl StdError + 'static) -> BX {
BX::from_err(e)
}

/// Adds `bx() -> BX` to error types
pub trait BxForErrors {
fn bx(self) -> BX;
}

impl<E: StdError + 'static> BxForErrors for E {
fn bx(self) -> BX {
BX::from_err(self)
}
}

/// Adds `bx() -> Result<T, BX>` to result types
pub trait BxForResults<T> {
fn bx(self) -> Result<T, BX>;
}

impl<T, E: StdError + 'static> BxForResults<T> for Result<T, E> {
fn bx(self) -> Result<T, BX> {
self.map_err(BX::from_err)
}
}

impl fmt::Debug for BX {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl fmt::Display for BX {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl StdError for BX {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.0.source()
}
}

/// Implements `From<E>` for `BX` for your own type.
#[macro_export]
macro_rules! make_bxable {
($ty:ty) => {
impl From<$ty> for $crate::BX {
fn from(e: $ty) -> Self {
$crate::BX::from_err(e)
}
}
};
}

make_bxable!(std::io::Error);
make_bxable!(std::fmt::Error);
make_bxable!(std::str::Utf8Error);
make_bxable!(std::string::FromUtf8Error);
make_bxable!(std::string::FromUtf16Error);
make_bxable!(std::num::ParseIntError);
make_bxable!(std::num::ParseFloatError);
make_bxable!(std::num::TryFromIntError);
make_bxable!(std::array::TryFromSliceError);
make_bxable!(std::char::ParseCharError);
make_bxable!(std::net::AddrParseError);
make_bxable!(std::time::SystemTimeError);
make_bxable!(std::env::VarError);
make_bxable!(std::sync::mpsc::RecvError);
make_bxable!(std::sync::mpsc::TryRecvError);
make_bxable!(std::sync::mpsc::SendError<Box<dyn StdError + Send + Sync>>);
make_bxable!(std::sync::PoisonError<Box<dyn StdError + Send + Sync>>);
2 changes: 1 addition & 1 deletion crates/buffet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ miri = []

[dependencies]
bytemuck = { version = "1.16.3", features = ["extern_crate_std"] }
eyre = "0.6.12"
http = "1.1.0"
libc = "0.2.155"
memchr = "2.7.4"
Expand All @@ -41,6 +40,7 @@ tokio = { version = "1.39.2", features = [
] }
tracing = "0.1.40"
nix = "0.29.0"
b-x = { version = "1.0.0", path = "../b-x" }

[target.'cfg(target_os = "linux")'.dependencies]
luring = { path = "../luring", version = "0.1.0", optional = true }
Expand Down
8 changes: 2 additions & 6 deletions crates/buffet/src/bufpool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ mod tests {
}

#[test]
fn freeze_test() -> eyre::Result<()> {
fn freeze_test() {
crate::bufpool::initialize_allocator().unwrap();

let total_bufs = num_free();
Expand All @@ -372,12 +372,10 @@ mod tests {

drop(b2);
assert_eq!(total_bufs, num_free());

Ok(())
}

#[test]
fn split_test() -> eyre::Result<()> {
fn split_test() {
crate::bufpool::initialize_allocator().unwrap();

let total_bufs = num_free();
Expand All @@ -391,7 +389,5 @@ mod tests {
assert_eq!(&b[..6], b"jacket");

drop((a, b));

Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/buffet/src/bufpool/privatepool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub enum Error {
DoesNotFit,
}

b_x::make_bxable!(Error);

thread_local! {
static POOL: Pool = const { Pool::new() };
}
Expand Down
21 changes: 13 additions & 8 deletions crates/buffet/src/roll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,27 +1288,32 @@ mod tests {
fn test_roll_iobuf() {
crate::bufpool::initialize_allocator().unwrap();

use b_x::{BxForResults, BX};

use crate::{
io::{IntoHalves, ReadOwned, WriteOwned},
io::IntoHalves,
net::{TcpListener, TcpStream},
ReadOwned, WriteOwned,
};

async fn test_roll_iobuf_inner(mut rm: RollMut) -> eyre::Result<()> {
async fn test_roll_iobuf_inner(mut rm: RollMut) -> b_x::Result<()> {
rm.put(b"hello").unwrap();
let roll = rm.take_all();

let ln = TcpListener::bind("127.0.0.1:0".parse()?).await?;
let local_addr = ln.local_addr()?;
let ln = TcpListener::bind("127.0.0.1:0".parse().unwrap())
.await
.unwrap();
let local_addr = ln.local_addr().unwrap();

let send_fut = async move {
let stream = TcpStream::connect(local_addr).await?;
let stream = TcpStream::connect(local_addr).await.bx()?;
let (_stream_r, mut stream_w) = IntoHalves::into_halves(stream);
stream_w.write_all_owned(roll).await?;
Ok::<_, eyre::Report>(())
Ok::<_, BX>(())
};

let recv_fut = async move {
let (stream, addr) = ln.accept().await?;
let (stream, addr) = ln.accept().await.bx()?;
let (mut stream_r, _stream_w) = IntoHalves::into_halves(stream);
println!("Accepted connection from {addr}");

Expand All @@ -1319,7 +1324,7 @@ mod tests {

assert_eq!(&buf[..n], b"hello");

Ok::<_, eyre::Report>(())
Ok::<_, BX>(())
};

tokio::try_join!(send_fut, recv_fut)?;
Expand Down
2 changes: 2 additions & 0 deletions crates/httpwg-loona/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ buffet = { version = "0.2.1", path = "../buffet" }
tracing = { version = "0.1.40", features = ["release_max_level_debug"] }
tracing-subscriber = "0.3.18"
tokio = { version = "1.39.2", features = ["macros", "sync", "process"] }
eyre = { version = "0.6.12", default-features = false }
b-x = { version = "1.0.0", path = "../b-x" }

[dev-dependencies]
codspeed-criterion-compat = "2.6.0"
5 changes: 3 additions & 2 deletions crates/httpwg-loona/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use b_x::{BxForResults, BX};
use std::{cell::RefCell, rc::Rc};
use tokio::{process::Command, sync::oneshot};

Expand Down Expand Up @@ -168,7 +169,7 @@ impl<OurEncoder> ServerDriver<OurEncoder> for TestDriver
where
OurEncoder: Encoder,
{
type Error = Box<dyn std::error::Error>;
type Error = BX;

async fn handle(
&self,
Expand All @@ -190,7 +191,7 @@ where
// then read the full request body
let mut req_body_len = 0;
loop {
let chunk = req_body.next_chunk().await?;
let chunk = req_body.next_chunk().await.bx()?;
match chunk {
BodyChunk::Done { trailers } => {
// yey
Expand Down
1 change: 1 addition & 0 deletions crates/httpwg/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ futures-util = "0.3.30"
pretty-hex = "0.4.1"
tokio = { version = "1.39.2", features = ["time"] }
tracing = "0.1.40"
b-x = { version = "1.0.0", path = "../b-x" }
1 change: 1 addition & 0 deletions crates/loona/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ thiserror = { version = "1.0.63", default-features = false }
tokio = { version = "1.39.2", features = ["macros", "sync"] }
tracing = { version = "0.1.40", default-features = false }
loona-h2 = { version = "0.2.1", path = "../loona-h2" }
b-x = { version = "1.0.0", path = "../b-x" }

[dev-dependencies]
buffet = { version = "0.2.1", path = "../buffet" }
Expand Down
19 changes: 6 additions & 13 deletions crates/loona/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::error::Error as StdError;
use std::fmt;

use crate::h2::types::H2ConnectionError;
use b_x::BX;

pub type BoxError = Box<dyn StdError>;
use crate::h2::types::H2ConnectionError;

/// Any error that can occur when servicing a connection
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum ServeError<DriverError> {
Expand All @@ -31,23 +30,17 @@ pub enum ServeError<DriverError> {
Alloc(#[from] buffet::bufpool::Error),
}

impl<DriverError> AsRef<dyn StdError> for ServeError<DriverError>
impl<DriverError> From<ServeError<DriverError>> for BX
where
DriverError: AsRef<dyn StdError> + fmt::Debug + 'static,
DriverError: std::error::Error + 'static,
{
fn as_ref(&self) -> &(dyn StdError + 'static) {
self
fn from(e: ServeError<DriverError>) -> Self {
BX::from_err(e)
}
}

pub struct NeverError;

impl AsRef<dyn StdError> for NeverError {
fn as_ref(&self) -> &(dyn StdError + 'static) {
self
}
}

impl fmt::Debug for NeverError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("NeverError")
Expand Down
Loading

0 comments on commit 73c5acd

Please sign in to comment.