Use Error trait from core
This patch gets rid of the `anyhow` dependency in favor of `core::error::Error` and sets the MSRV to 1.81.0
- Id
- f93b2020a487186b9298ceecb859c0921c013a24
- Author
- Caio
- Commit time
- 2024-09-05T23:37:01+02:00
Modified Cargo.toml
[package]
name = "foca"
version = "0.17.2"
-rust-version = "1.70.0"
+rust-version = "1.81.0"
authors = ["Caio <contact@caio.co>"]
edition = "2021"
license = "MPL-2.0"
default = []
# Adds compatibility with some types and traits
-std = ["anyhow/std"]
+std = []
# Exposes `BincodeCodec` a lean general-purpose std-only codec
bincode-codec = ["std", "serde", "bincode", "bytes/std"]
# Exposes `PostcardCodec`, a no_std-friendly codec
[dependencies]
rand = { version = "0.8", default-features = false }
bytes = { version = "1", default-features = false }
-anyhow = { version = "1", default-features = false }
serde = { version = "1", default-features = false, features = ["derive", "alloc"], optional = true }
bincode = { version = "1", default-features = false, optional = true }
Modified examples/foca_insecure_udp_agent.rs
}
}
+#[derive(Debug)]
+struct Msg(String);
+
+impl core::fmt::Display for Msg {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl core::error::Error for Msg {}
+
impl foca::BroadcastHandler<ID> for Handler {
type Key = BroadcastKey;
- type Error = String;
+ type Error = Msg;
fn receive_item(
&mut self,
let Broadcast { key, msg }: Broadcast = self
.opts
.deserialize_from(&mut reader)
- .map_err(|err| format!("bad broadcast: {err}"))?;
+ .map_err(|err| Msg(format!("bad broadcast: {err}")))?;
let is_new_message = self
.messages
Modified src/broadcast.rs
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use alloc::vec::Vec;
-use core::{cmp::Ordering, fmt};
+use core::cmp::Ordering;
use bytes::BufMut;
/// The error type that `receive_item` may emit. Will be wrapped
/// by [`crate::Error::CustomBroadcast`].
- type Error: fmt::Debug + fmt::Display + Send + Sync + 'static;
+ type Error: core::error::Error + Send + 'static;
/// Decodes a [`Self::Key`] from a buffer and either discards
/// it or tells Foca to persist and disseminate it.
Modified src/error.rs
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use core::fmt;
+use alloc::boxed::Box;
+
#[derive(Debug)]
/// This type represents all possible errors operating a Foca instance.
pub enum Error {
/// codec.
///
/// Might have left Foca in a inconsistent state.
- Encode(anyhow::Error),
+ Encode(Box<dyn core::error::Error + Send>),
/// Wraps [`crate::Codec`]'s `decode_*` failures.
///
/// Can happen during normal operation when receiving junk data.
- Decode(anyhow::Error),
+ Decode(Box<dyn core::error::Error + Send>),
/// Wraps [`crate::BroadcastHandler`] failures.
///
/// Doesn't affect Foca's state.
- CustomBroadcast(anyhow::Error),
+ CustomBroadcast(Box<dyn core::error::Error + Send>),
/// Configuration change not allowed.
///
Modified src/lib.rs
)]
extern crate alloc;
-use alloc::vec::Vec;
+use alloc::{boxed::Box, vec::Vec};
#[cfg(feature = "std")]
extern crate std;
where
T: Identity,
C: Codec<T>,
+ C::Error: core::error::Error + Send,
RNG: Rng,
{
/// Create a new Foca instance with custom broadcasts disabled.
}
}
-// XXX Does it make sense to have different associated type restrictions
-// based on a feature flag? Say: when using `std` we would enforce
-// that `Codec::Error` and `BroadcastHandler::Error` both implement
-// `std::error::Error`, thus instead of wrapping these errors via
-// `anyhow::Error::msg` we can use `anyhow::Error::new`.
impl<T, C, RNG, B> Foca<T, C, RNG, B>
where
T: Identity,
C: Codec<T>,
+ C::Error: core::error::Error,
RNG: Rng,
B: BroadcastHandler<T>,
+ B::Error: core::error::Error + 'static,
{
/// Initialize a new Foca instance.
pub fn with_custom_broadcast(
if let Some(key) = self
.broadcast_handler
.receive_item(data, None)
- .map_err(anyhow::Error::msg)
- .map_err(Error::CustomBroadcast)?
+ .map_err(|e| Error::CustomBroadcast(Box::new(e)))?
{
self.custom_broadcasts.add_or_replace(
key,
let header = self
.codec
.decode_header(&mut data)
- .map_err(anyhow::Error::msg)
- .map_err(Error::Decode)?;
+ .map_err(|e| Error::Decode(Box::new(e)))?;
#[cfg(feature = "tracing")]
span.record("header", tracing::field::debug(&header));
self.member_buf.push(
self.codec
.decode_member(&mut data)
- .map_err(anyhow::Error::msg)
- .map_err(Error::Decode)?,
+ .map_err(|e| Error::Decode(Box::new(e)))?,
);
}
}
let mut buf = Vec::new();
self.codec
.encode_member(&member, &mut buf)
- .map_err(anyhow::Error::msg)
- .map_err(Error::Encode)?;
+ .map_err(|e| Error::Encode(Box::new(e)))?;
Ok(buf)
}
if let Some(key) = self
.broadcast_handler
.receive_item(pkt, sender)
- .map_err(anyhow::Error::msg)
- .map_err(Error::CustomBroadcast)?
+ .map_err(|e| Error::CustomBroadcast(Box::new(e)))?
{
#[cfg(feature = "tracing")]
tracing::trace!(len = pkt_len, "received broadcast item");
if let Err(err) = self
.codec
.encode_header(&header, &mut buf)
- .map_err(anyhow::Error::msg)
- .map_err(Error::Encode)
+ .map_err(|e| Error::Encode(Box::new(e)))
{
debug_assert_eq!(0, self.send_buf.capacity(), "send_buf modified while taken");
self.send_buf = buf.into_inner();
}
}
-#[cfg(feature = "std")]
-impl std::error::Error for BroadcastsDisabledError {}
+impl core::error::Error for BroadcastsDisabledError {}
impl<T> BroadcastHandler<T> for NoCustomBroadcast {
type Key = &'static [u8];
where
T: Identity,
C: Codec<T>,
+ C::Error: core::error::Error,
RNG: rand::Rng,
B: BroadcastHandler<T>,
+ B::Error: core::error::Error + Send,
{
pub fn incarnation(&self) -> Incarnation {
self.incarnation
}
}
+ impl core::error::Error for UnitError {}
+
impl Codec<ID> for UnitErroringCodec {
type Error = UnitError;
let mut foca = Foca::new(ID::new(1), Config::simple(), rng(), UnitErroringCodec);
assert_eq!(
- Err(Error::Encode(anyhow::Error::msg(UnitError))),
+ Err(Error::Encode(alloc::boxed::Box::new(UnitError))),
foca.announce(ID::new(2), NoopRuntime)
);
assert_eq!(
- Err(Error::Decode(anyhow::Error::msg(UnitError))),
+ Err(Error::Decode(alloc::boxed::Box::new(UnitError))),
foca.handle_data(b"hue", NoopRuntime)
);
}
buf.get_u16()
}
- fn from_bytes(mut src: impl Buf) -> core::result::Result<Self, &'static str> {
+ fn from_bytes(mut src: impl Buf) -> core::result::Result<Self, Msg> {
if src.remaining() < 10 {
- Err("buffer too small")
+ Err(Msg("buffer too small"))
} else {
let mut data = [0u8; 10];
let mut buf = &mut data[..];
use alloc::collections::BTreeMap;
struct Handler(BTreeMap<u64, u16>);
+ #[derive(Debug)]
+ struct Msg(&'static str);
+
+ impl core::fmt::Display for Msg {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+ }
+
+ impl core::error::Error for Msg {}
+
impl BroadcastHandler<ID> for Handler {
type Key = VersionedKey;
- type Error = &'static str;
+ type Error = Msg;
fn receive_item(
&mut self,
}
}
+ #[derive(Debug)]
+ struct Msg(&'static str);
+
+ impl core::fmt::Display for Msg {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+ }
+
+ impl core::error::Error for Msg {}
+
impl BroadcastHandler<ID> for DumbHandler {
type Key = GrowOnly;
- type Error = &'static str;
+ type Error = Msg;
fn receive_item(
&mut self,
Modified src/testing.rs
}
}
+impl core::error::Error for BadCodecError {}
+
impl BadCodec {
fn encode_header(
&self,