Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name = "init4-bin-base"
description = "Internal utilities for binaries produced by the init4 team"
keywords = ["init4", "bin", "base"]

version = "0.9.1"
version = "0.9.2"
edition = "2021"
rust-version = "1.81"
authors = ["init4", "James Prestwich"]
Expand Down
28 changes: 25 additions & 3 deletions src/utils/from_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use signet_constants::{
SignetSystemConstants,
};
use std::{convert::Infallible, env::VarError, num::ParseIntError, str::FromStr};
use tracing_core::metadata::ParseLevelError;

/// The `derive(FromEnv)` macro.
///
Expand Down Expand Up @@ -278,7 +279,7 @@ pub fn parse_env_if_present<T: FromStr>(env_var: &str) -> Result<T, FromEnvErr<T
///
pub trait FromEnv: core::fmt::Debug + Sized + 'static {
/// Error type produced when loading from the environment.
type Error: core::error::Error + Clone;
type Error: core::error::Error + Clone + PartialEq + Eq;

/// Get the required environment variable names for this type.
///
Expand Down Expand Up @@ -453,7 +454,7 @@ where
/// ```
pub trait FromEnvVar: core::fmt::Debug + Sized + 'static {
/// Error type produced when parsing the primitive.
type Error: core::error::Error;
type Error: core::error::Error + Clone + PartialEq + Eq;

/// Load the primitive from the environment at the given variable.
fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>>;
Expand Down Expand Up @@ -613,7 +614,6 @@ impl_for_parseable!(
i128,
isize,
url::Url,
tracing::Level,
SignetConstants,
SignetEnvironmentConstants,
SignetSystemConstants,
Expand Down Expand Up @@ -646,6 +646,28 @@ impl FromEnvVar for bool {
}
}

/// Error type for parsing tracing levels from the environment.
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[error("failed to parse tracing level from environment variable")]
pub struct LevelParseError;

impl From<ParseLevelError> for LevelParseError {
fn from(_: ParseLevelError) -> Self {
LevelParseError
}
}

impl FromEnvVar for tracing::Level {
type Error = LevelParseError;

fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
let s: String = std::env::var(env_var).map_err(|e| FromEnvErr::env_err(env_var, e))?;
s.parse()
.map_err(Into::into)
.map_err(FromEnvErr::parse_error)
}
}

#[cfg(test)]
mod test {
use std::{borrow::Cow, time::Duration};
Expand Down
58 changes: 52 additions & 6 deletions src/utils/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,43 @@ use alloy::{
},
};

/// Errors when connecting a provider
#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
pub enum ProviderConnectError {
/// Pubsub is not available for the configured transport
#[error("pubsub is not available for the configured transport")]
PubsubUnavailable,
/// Custom error message
#[error("{0}")]
Custom(String),
}

impl From<TransportErrorKind> for ProviderConnectError {
fn from(err: TransportErrorKind) -> Self {
match err {
TransportErrorKind::Custom(err) => ProviderConnectError::Custom(err.to_string()),
TransportErrorKind::PubsubUnavailable => ProviderConnectError::PubsubUnavailable,
_ => panic!("Unexpected TransportErrorKind variant: {err:?}"),
}
}
}

impl From<TransportError> for ProviderConnectError {
fn from(err: TransportError) -> Self {
match err {
TransportError::Transport(e) => e.into(),
_ => panic!("Unexpected TransportError variant: {err:?}"),
}
}
}

impl FromEnvVar for BuiltInConnectionString {
type Error = TransportError;
type Error = ProviderConnectError;

fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
let conn_str = String::from_env_var(env_var).map_err(FromEnvErr::infallible_into)?;
conn_str.parse().map_err(Into::into)
let built_in = conn_str.parse().map_err(ProviderConnectError::from)?;
Ok(built_in)
}
}

Expand Down Expand Up @@ -41,7 +72,7 @@ impl ProviderConfig {
}

impl FromEnvVar for ProviderConfig {
type Error = TransportError;
type Error = ProviderConnectError;

fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
let connection_string = BuiltInConnectionString::from_env_var(env_var)?;
Expand Down Expand Up @@ -81,21 +112,21 @@ impl PubSubConfig {
}

impl TryFrom<BuiltInConnectionString> for PubSubConfig {
type Error = TransportError;
type Error = ProviderConnectError;

fn try_from(connection_string: BuiltInConnectionString) -> Result<Self, Self::Error> {
if !matches!(
connection_string,
BuiltInConnectionString::Ws(_, _) | BuiltInConnectionString::Ipc(_)
) {
return Err(TransportErrorKind::pubsub_unavailable());
return Err(ProviderConnectError::PubsubUnavailable);
}
Ok(Self { connection_string })
}
}

impl FromEnvVar for PubSubConfig {
type Error = TransportError;
type Error = ProviderConnectError;

fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
let cs = BuiltInConnectionString::from_env_var(env_var)?;
Expand Down Expand Up @@ -137,3 +168,18 @@ impl PubSubConnect for PubSubConfig {
}
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::utils::from_env::FromEnv;

#[derive(FromEnv, Debug, Clone, PartialEq, Eq)]
#[from_env(crate)]
struct CompileCheck {
#[from_env(var = "COOL_DUDE", desc = "provider")]
cool_dude: ProviderConfig,
#[from_env(var = "COOL_DUDE2", desc = "provider2")]
cool_dude2: PubSubConfig,
}
}