From 2cb73fbae1511066b886ad9beb2ac2301d926423 Mon Sep 17 00:00:00 2001 From: Fraser Hutchison <190532+Fraser999@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:43:41 +0000 Subject: [PATCH] update FromEnvErr::ParseError --- Cargo.toml | 4 +- from-env-derive/Cargo.toml | 5 +- from-env-derive/src/field.rs | 107 ++--------------- from-env-derive/src/lib.rs | 110 +----------------- src/perms/builders.rs | 4 +- src/perms/mod.rs | 4 +- src/utils/calc.rs | 6 +- src/utils/from_env.rs | 217 ++++++++++------------------------- src/utils/metrics.rs | 4 +- src/utils/otlp.rs | 4 +- src/utils/provider.rs | 18 ++- 11 files changed, 88 insertions(+), 395 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3dc1416..69166fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "init4-bin-base" description = "Internal utilities for binaries produced by the init4 team" keywords = ["init4", "bin", "base"] -version = "0.18.0-rc.7" +version = "0.18.0-rc.8" edition = "2021" rust-version = "1.85" authors = ["init4", "James Prestwich", "evalir"] @@ -12,7 +12,7 @@ homepage = "https://github.com/init4tech/bin-base" repository = "https://github.com/init4tech/bin-base" [dependencies] -init4-from-env-derive = "0.1.0" +init4-from-env-derive = { version = "0.2.0", path = "from-env-derive" } # Signet signet-constants = { version = "0.16.0-rc.7" } diff --git a/from-env-derive/Cargo.toml b/from-env-derive/Cargo.toml index 37cbc44..64abeb2 100644 --- a/from-env-derive/Cargo.toml +++ b/from-env-derive/Cargo.toml @@ -2,7 +2,7 @@ name = "init4-from-env-derive" description = "A derive macro for `init4_bin_base::FromEnv`" -version = "0.1.2" +version = "0.2.0" edition = "2021" rust-version = "1.81" authors = ["init4", "James Prestwich"] @@ -11,7 +11,6 @@ homepage = "https://github.com/init4tech/bin-base" repository = "https://github.com/init4tech/bin-base" [dependencies] -heck = "0.5.0" proc-macro2 = "1.0.95" quote = "1.0.40" syn = { version = "2.0.100", features = ["full", "parsing"] } @@ -20,4 +19,4 @@ syn = { version = "2.0.100", features = ["full", "parsing"] } proc-macro = true [dev-dependencies] -init4-bin-base = "0.9" +init4-bin-base = { path = ".." } diff --git a/from-env-derive/src/field.rs b/from-env-derive/src/field.rs index 11737ba..e780473 100644 --- a/from-env-derive/src/field.rs +++ b/from-env-derive/src/field.rs @@ -1,4 +1,3 @@ -use heck::ToPascalCase; use proc_macro2::TokenStream; use quote::quote; use syn::{spanned::Spanned, Ident, LitStr}; @@ -89,26 +88,6 @@ impl TryFrom<&syn::Field> for Field { } impl Field { - pub(crate) fn trait_name(&self) -> TokenStream { - self.env_var - .as_ref() - .map(|_| quote! { FromEnvVar }) - .unwrap_or(quote! { FromEnv }) - } - - pub(crate) fn as_trait(&self) -> TokenStream { - let field_trait = self.trait_name(); - let field_type = &self.field_type; - - quote! { <#field_type as #field_trait> } - } - - pub(crate) fn assoc_err(&self) -> TokenStream { - let as_trait = self.as_trait(); - - quote! { #as_trait::Error } - } - pub(crate) fn field_name(&self, idx: usize) -> Ident { if let Some(field_name) = self.field_name.as_ref() { return field_name.clone(); @@ -120,41 +99,7 @@ impl Field { .unwrap() } - /// Produces the name of the enum variant for the field - pub(crate) fn enum_variant_name(&self, idx: usize) -> Option { - if self.skip || self.infallible { - return None; - } - - let n = self.field_name(idx).to_string().to_pascal_case(); - - let n: Ident = syn::parse_str::(&n) - .map_err(|_| syn::Error::new(self.span, "Failed to create field name")) - .unwrap(); - - Some(quote! { #n }) - } - - /// Produces the variant, containing the error type - pub(crate) fn expand_enum_variant(&self, idx: usize) -> Option { - let variant_name = self.enum_variant_name(idx)?; - let var_name_str = variant_name.to_string(); - let assoc_err = self.assoc_err(); - - Some(quote! { - #[doc = "Error for "] - #[doc = #var_name_str] - #variant_name(#assoc_err) - }) - } - - /// Produces the a line for the `inventory` function - /// of the form - /// items.push(...); // (if this is a FromEnvVar) - /// or - /// items.extend(...); // (if this is a FromEnv) - /// or - /// // nothing if this is a skip + /// Produces a line for the `inventory` function pub(crate) fn expand_env_item_info(&self) -> TokenStream { if self.skip { return quote! {}; @@ -183,39 +128,7 @@ impl Field { } } - pub(crate) fn expand_variant_display(&self, idx: usize) -> Option { - let variant_name = self.enum_variant_name(idx)?; - - Some(quote! { - Self::#variant_name(err) => err.fmt(f) - }) - } - - pub(crate) fn expand_variant_source(&self, idx: usize) -> Option { - let variant_name = self.enum_variant_name(idx)?; - - Some(quote! { - Self::#variant_name(err) => Some(err) - }) - } - - pub(crate) fn expand_item_from_env(&self, err_ident: &syn::Path, idx: usize) -> TokenStream { - // Produces code fo the following form: - // ```rust - // // EITHER - // let field_name = env::var(#self.env_var.unwrap()).map_err(|e| e.map(#ErroEnum::FieldName))?; - - // // OR - // let field_name = FromEnvVar::from_env_var(#self.env_var.unwrap()).map_err(|e| e.map(#ErroEnum::FieldName))?; - - // // OR - // let field_name = FromEnv::from_env().map_err()?; - - // // OR - // let field_name = Default::default(); - - //``` - let variant = self.enum_variant_name(idx); + pub(crate) fn expand_item_from_env(&self, idx: usize) -> TokenStream { let field_name = self.field_name(idx); if self.skip { @@ -230,15 +143,15 @@ impl Field { quote! { FromEnv::from_env() } }; - let map_line = if self.infallible { - quote! { FromEnvErr::infallible_into } + if self.infallible { + quote! { + let #field_name = #fn_invoc + .map_err(FromEnvErr::infallible_into)?; + } } else { - quote! { |e| e.map(#err_ident::#variant) } - }; - - quote! { - let #field_name = #fn_invoc - .map_err(#map_line)?; + quote! { + let #field_name = #fn_invoc?; + } } } } diff --git a/from-env-derive/src/lib.rs b/from-env-derive/src/lib.rs index 2cfabb3..5a6b570 100644 --- a/from-env-derive/src/lib.rs +++ b/from-env-derive/src/lib.rs @@ -102,101 +102,14 @@ impl Input { } } - fn error_ident(&self) -> syn::Path { - if self.is_infallible() { - return syn::parse_str("::std::convert::Infallible").unwrap(); - } - - let error_name = format!("{}EnvError", self.ident); - syn::parse_str::(&error_name) - .map_err(|_| { - syn::Error::new(self.ident.span(), "Failed to parse error ident").to_compile_error() - }) - .unwrap() - } - - fn is_infallible(&self) -> bool { - self.error_variants().is_empty() - } - - fn error_variants(&self) -> Vec { - self.fields - .iter() - .enumerate() - .flat_map(|(idx, field)| field.expand_enum_variant(idx)) - .collect() - } - - fn error_variant_displays(&self) -> Vec { - self.fields - .iter() - .enumerate() - .flat_map(|(idx, field)| field.expand_variant_display(idx)) - .collect::>() - } - - fn expand_variant_sources(&self) -> Vec { - self.fields - .iter() - .enumerate() - .flat_map(|(idx, field)| field.expand_variant_source(idx)) - .collect::>() - } - fn item_from_envs(&self) -> Vec { - let error_ident = self.error_ident(); self.fields .iter() .enumerate() - .map(|(idx, field)| field.expand_item_from_env(&error_ident, idx)) + .map(|(idx, field)| field.expand_item_from_env(idx)) .collect() } - fn expand_error(&self) -> TokenStream { - let error_ident = self.error_ident(); - let struct_name_str = &self.ident.to_string(); - - let error_variants = self.error_variants(); - let error_variant_displays = self.error_variant_displays(); - let error_variant_sources = self.expand_variant_sources(); - - if error_variants.is_empty() { - return Default::default(); - } - - quote! { - #[doc = "Generated error type for [`FromEnv`] for"] - #[doc = #struct_name_str] - #[doc = ". This error type is used to represent errors that occur when trying to create an instance of the struct from environment variables."] - #[derive(Debug, PartialEq, Eq, Clone)] - pub enum #error_ident { - #(#error_variants),* - } - - #[automatically_derived] - impl ::core::fmt::Display for #error_ident { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - #( - #error_variant_displays, - )* - } - } - } - - #[automatically_derived] - impl ::core::error::Error for #error_ident { - fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> { - match self { - #( - #error_variant_sources, - )* - } - } - } - } - } - fn env_item_info(&self) -> Vec { self.fields .iter() @@ -208,16 +121,12 @@ impl Input { let env_item_info = self.env_item_info(); let struct_name = &self.ident; - let error_ident = self.error_ident(); - let item_from_envs = self.item_from_envs(); let struct_instantiation = self.instantiate_struct(); quote! { #[automatically_derived] impl FromEnv for #struct_name { - type Error = #error_ident; - fn inventory() -> ::std::vec::Vec<&'static EnvItemInfo> { let mut items = ::std::vec::Vec::new(); #( @@ -226,7 +135,7 @@ impl Input { items } - fn from_env() -> ::std::result::Result> { + fn from_env() -> ::std::result::Result { #( #item_from_envs )* @@ -238,33 +147,18 @@ impl Input { } fn expand_mod(&self) -> TokenStream { - // let expanded_impl = expand_impl(input); let expanded_impl = self.expand_impl(); let crate_name = &self.crate_name; let mod_ident = syn::parse_str::(&format!("__from_env_impls_{}", self.ident)).unwrap(); - let expanded_error = self.expand_error(); - - let use_err = if !expanded_error.is_empty() { - let error_ident = self.error_ident(); - quote! { - pub use #mod_ident::#error_ident; - } - } else { - quote! {} - }; - quote! { - #use_err mod #mod_ident { use super::*; use #crate_name::utils::from_env::{FromEnv, FromEnvErr, FromEnvVar, EnvItemInfo}; #expanded_impl - - #expanded_error } } } diff --git a/src/perms/builders.rs b/src/perms/builders.rs index 0adcb0f..5bf931d 100644 --- a/src/perms/builders.rs +++ b/src/perms/builders.rs @@ -66,9 +66,7 @@ impl Builder { } impl FromEnvVar for Builder { - type Error = std::convert::Infallible; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { Ok(Self { sub: String::from_env_var(env_var)?, }) diff --git a/src/perms/mod.rs b/src/perms/mod.rs index 9bfd552..264bd5e 100644 --- a/src/perms/mod.rs +++ b/src/perms/mod.rs @@ -1,8 +1,8 @@ pub(crate) mod builders; -pub use builders::{Builder, BuilderPermissionError, Builders, BuildersEnvError}; +pub use builders::{Builder, BuilderPermissionError, Builders}; pub(crate) mod config; -pub use config::{SlotAuthzConfig, SlotAuthzConfigEnvError}; +pub use config::SlotAuthzConfig; pub(crate) mod oauth; pub use oauth::{Authenticator, OAuthConfig, SharedToken}; diff --git a/src/utils/calc.rs b/src/utils/calc.rs index f9be097..81bb5d4 100644 --- a/src/utils/calc.rs +++ b/src/utils/calc.rs @@ -1,7 +1,7 @@ use crate::utils::from_env::{EnvItemInfo, FromEnv, FromEnvErr, FromEnvVar}; #[allow(deprecated)] use signet_constants::{mainnet, parmigiana, pecorino, test_utils, KnownChains}; -use std::{num::ParseIntError, str::FromStr}; +use std::str::FromStr; /// A slot calculator, which can calculate slot numbers, windows, and offsets /// for a given chain. @@ -293,8 +293,6 @@ impl SlotCalculator { } impl FromEnv for SlotCalculator { - type Error = ParseIntError; - fn inventory() -> Vec<&'static EnvItemInfo> { vec![ &EnvItemInfo { @@ -320,7 +318,7 @@ impl FromEnv for SlotCalculator { ] } - fn from_env() -> Result> { + fn from_env() -> Result { if let Ok(slot_calculator) = SlotCalculator::from_env_var("CHAIN_NAME") { return Ok(slot_calculator); } diff --git a/src/utils/from_env.rs b/src/utils/from_env.rs index c2d429f..1bf51ea 100644 --- a/src/utils/from_env.rs +++ b/src/utils/from_env.rs @@ -1,8 +1,8 @@ use signet_constants::{ - HostConstants, ParseChainError, RollupConstants, SignetConstants, SignetEnvironmentConstants, + HostConstants, RollupConstants, SignetConstants, SignetEnvironmentConstants, SignetSystemConstants, }; -use std::{convert::Infallible, env::VarError, num::ParseIntError, str::FromStr}; +use std::{env::VarError, str::FromStr}; use tracing_core::metadata::ParseLevelError; use crate::utils::calc::SlotCalculator; @@ -153,8 +153,8 @@ pub struct EnvItemInfo { /// Error type for loading from the environment. See the [`FromEnv`] trait for /// more information. -#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] -pub enum FromEnvErr { +#[derive(Debug, thiserror::Error)] +pub enum FromEnvErr { /// The environment variable is missing. #[error("error reading variable {0}: {1}")] EnvError(String, VarError), @@ -162,45 +162,22 @@ pub enum FromEnvErr { #[error("environment variable {0} is empty")] Empty(String), /// The environment variable is present, but the value could not be parsed. - #[error("failed to parse environment variable {0}")] - ParseError(#[from] Inner), + #[error("failed to parse environment variable {0}: {1}")] + ParseError(String, #[source] Box), } -impl FromEnvErr { +impl FromEnvErr { /// Convert the error into another error type. - pub fn infallible_into(self) -> FromEnvErr { + pub fn infallible_into(self) -> FromEnvErr { match self { Self::EnvError(s, e) => FromEnvErr::EnvError(s, e), Self::Empty(s) => FromEnvErr::Empty(s), - Self::ParseError(_) => unreachable!(), + Self::ParseError(..) => unreachable!(), } } } -impl FromEnvErr { - /// Create a new error from another error type. - pub fn from(other: FromEnvErr) -> Self - where - Inner: From, - { - match other { - FromEnvErr::EnvError(s, e) => Self::EnvError(s, e), - FromEnvErr::Empty(s) => Self::Empty(s), - FromEnvErr::ParseError(e) => Self::ParseError(Inner::from(e)), - } - } - - /// Map the error to another type. This is useful for converting the error - /// type to a different type, while keeping the other error information - /// intact. - pub fn map(self, f: impl FnOnce(Inner) -> New) -> FromEnvErr { - match self { - Self::EnvError(s, e) => FromEnvErr::EnvError(s, e), - Self::Empty(s) => FromEnvErr::Empty(s), - Self::ParseError(e) => FromEnvErr::ParseError(f(e)), - } - } - +impl FromEnvErr { /// Missing env var. pub fn env_err(var: &str, e: VarError) -> Self { Self::EnvError(var.to_string(), e) @@ -212,20 +189,28 @@ impl FromEnvErr { } /// Error while parsing. - pub const fn parse_error(err: Inner) -> Self { - Self::ParseError(err) + pub fn parse_error(var: &str, err: E) -> Self + where + E: core::error::Error + Send + Sync + 'static, + { + Self::ParseError(var.to_string(), Box::new(err)) } } /// Convenience function for parsing a value from the environment, if present /// and non-empty. -pub fn parse_env_if_present(env_var: &str) -> Result> { +pub fn parse_env_if_present(env_var: &str) -> Result +where + T: FromStr, + T::Err: core::error::Error + Send + Sync + 'static, +{ let s = std::env::var(env_var).map_err(|e| FromEnvErr::env_err(env_var, e))?; if s.is_empty() { Err(FromEnvErr::empty(env_var)) } else { - s.parse().map_err(Into::into) + s.parse() + .map_err(|error| FromEnvErr::ParseError(env_var.to_owned(), Box::new(error))) } } @@ -260,28 +245,11 @@ pub fn parse_env_if_present(env_var: &str) -> Result`] as -/// the `Error` associated type in [`FromEnv`].** -/// -/// ```no_compile -/// // Do not do this -/// impl FromEnv for MyType { -/// type Error = FromEnvErr; -/// } -/// -/// // Instead do this: -/// impl FromEnv for MyType { -/// type Error = MyTypeErr; -/// } -/// ``` -/// +/// top level, and should never be nested. pub trait FromEnv: core::fmt::Debug + Sized + 'static { - /// Error type produced when loading from the environment. - type Error: core::error::Error + Clone + PartialEq + Eq; - /// Get the required environment variable names for this type. /// /// ## Note @@ -310,15 +278,13 @@ pub trait FromEnv: core::fmt::Debug + Sized + 'static { } /// Load from the environment. - fn from_env() -> Result>; + fn from_env() -> Result; } impl FromEnv for Option where T: FromEnv, { - type Error = T::Error; - fn inventory() -> Vec<&'static EnvItemInfo> { T::inventory() } @@ -327,7 +293,7 @@ where T::check_inventory() } - fn from_env() -> Result> { + fn from_env() -> Result { match T::from_env() { Ok(v) => Ok(Some(v)), Err(FromEnvErr::Empty(_)) | Err(FromEnvErr::EnvError(_, _)) => Ok(None), @@ -340,8 +306,6 @@ impl FromEnv for Box where T: FromEnv, { - type Error = T::Error; - fn inventory() -> Vec<&'static EnvItemInfo> { T::inventory() } @@ -350,7 +314,7 @@ where T::check_inventory() } - fn from_env() -> Result> { + fn from_env() -> Result { T::from_env().map(Box::new) } } @@ -359,8 +323,6 @@ impl FromEnv for std::sync::Arc where T: FromEnv, { - type Error = T::Error; - fn inventory() -> Vec<&'static EnvItemInfo> { T::inventory() } @@ -369,7 +331,7 @@ where T::check_inventory() } - fn from_env() -> Result> { + fn from_env() -> Result { T::from_env().map(std::sync::Arc::new) } } @@ -379,8 +341,6 @@ where T: FromEnv, U: std::borrow::ToOwned + core::fmt::Debug + ?Sized, { - type Error = T::Error; - fn inventory() -> Vec<&'static EnvItemInfo> { T::inventory() } @@ -389,7 +349,7 @@ where T::check_inventory() } - fn from_env() -> Result> { + fn from_env() -> Result { T::from_env().map(std::borrow::Cow::Owned) } } @@ -406,23 +366,10 @@ where /// /// [`FromEnv`] and [`FromEnvVar`] are often deeply nested. This means that /// error types are often nested as well. To avoid this, we use a single error -/// type [`FromEnvVar`] that wraps an inner error type. This allows us to +/// type [`FromEnvErr`] that wraps an inner error type. This allows us to /// ensure that env-related errors (e.g. missing env vars) are not lost in the /// recursive structure of parsing errors. Environment errors are always at the -/// top level, and should never be nested. **Do not use [`FromEnvErr`] as -/// the `Error` associated type in [`FromEnv`].** -/// -/// ```no_compile -/// // Do not do this -/// impl FromEnv for MyType { -/// type Error = FromEnvErr; -/// } -/// -/// // Instead do this: -/// impl FromEnv for MyType { -/// type Error = MyTypeErr; -/// } -/// ``` +/// top level, and should never be nested. /// /// ## Implementing [`FromEnv`] /// @@ -445,27 +392,22 @@ where /// /// // We can re-use the `FromStr` implementation for our `FromEnvVar` impl. /// impl FromEnvVar for MyCoolType { -/// type Error = ::Err; -/// -/// fn from_env_var(env_var: &str) -> Result> +/// fn from_env_var(env_var: &str) -> Result /// { -/// String::from_env_var(env_var).unwrap().parse().map_err(Into::into) +/// Ok(String::from_env_var(env_var)?.parse().unwrap()) /// } /// } /// ``` pub trait FromEnvVar: core::fmt::Debug + Sized + 'static { - /// Error type produced when parsing the primitive. - 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>; + fn from_env_var(env_var: &str) -> Result; /// Load the primitive from the environment at the given variable. If the /// variable is unset or empty, return the default value. /// /// This function will return an error if the environment variable is set /// but cannot be parsed. - fn from_env_var_or(env_var: &str, default: Self) -> Result> { + fn from_env_var_or(env_var: &str, default: Self) -> Result { match Self::from_env_var(env_var) { Ok(v) => Ok(v), Err(FromEnvErr::Empty(_)) | Err(FromEnvErr::EnvError(_, _)) => Ok(default), @@ -482,7 +424,7 @@ pub trait FromEnvVar: core::fmt::Debug + Sized + 'static { fn from_env_var_or_else( env_var: &str, default: impl FnOnce() -> Self, - ) -> Result> { + ) -> Result { match Self::from_env_var(env_var) { Ok(v) => Ok(v), Err(FromEnvErr::Empty(_)) | Err(FromEnvErr::EnvError(_, _)) => Ok(default()), @@ -496,7 +438,7 @@ pub trait FromEnvVar: core::fmt::Debug + Sized + 'static { /// /// This function will return an error if the environment variable is set /// but cannot be parsed. - fn from_env_var_or_default(env_var: &str) -> Result> + fn from_env_var_or_default(env_var: &str) -> Result where Self: Default, { @@ -508,9 +450,7 @@ impl FromEnvVar for Option where T: FromEnvVar, { - type Error = T::Error; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { match std::env::var(env_var) { Ok(s) if s.is_empty() => Ok(None), Ok(_) => T::from_env_var(env_var).map(Some), @@ -523,9 +463,7 @@ impl FromEnvVar for Box where T: FromEnvVar, { - type Error = T::Error; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { T::from_env_var(env_var).map(Box::new) } } @@ -534,9 +472,7 @@ impl FromEnvVar for std::sync::Arc where T: FromEnvVar, { - type Error = T::Error; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { T::from_env_var(env_var).map(std::sync::Arc::new) } } @@ -544,27 +480,21 @@ where impl FromEnvVar for std::borrow::Cow<'static, U> where T: FromEnvVar, - U: std::borrow::ToOwned + core::fmt::Debug + ?Sized, + U: ToOwned + core::fmt::Debug + ?Sized, { - type Error = T::Error; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { T::from_env_var(env_var).map(std::borrow::Cow::Owned) } } impl FromEnvVar for String { - type Error = std::convert::Infallible; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { std::env::var(env_var).map_err(|_| FromEnvErr::empty(env_var)) } } impl FromEnvVar for std::time::Duration { - type Error = ParseIntError; - - fn from_env_var(s: &str) -> Result> { + fn from_env_var(s: &str) -> Result { u64::from_env_var(s).map(Self::from_millis) } } @@ -573,9 +503,7 @@ impl FromEnvVar for Vec where T: From + core::fmt::Debug + 'static, { - type Error = Infallible; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { let s = std::env::var(env_var).map_err(|e| FromEnvErr::env_err(env_var, e))?; if s.is_empty() { return Ok(vec![]); @@ -591,9 +519,7 @@ macro_rules! impl_for_parseable { ($($t:ty),*) => { $( impl FromEnvVar for $t { - type Error = <$t as FromStr>::Err; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { parse_env_if_present(env_var) } } @@ -632,17 +558,13 @@ impl_for_parseable!( #[cfg(feature = "alloy")] impl FromEnvVar for alloy::primitives::FixedBytes { - type Error = as FromStr>::Err; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { parse_env_if_present(env_var) } } impl FromEnvVar for bool { - type Error = std::str::ParseBoolError; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { let s: String = std::env::var(env_var).map_err(|e| FromEnvErr::env_err(env_var, e))?; Ok(!s.is_empty()) } @@ -660,19 +582,15 @@ impl From for LevelParseError { } impl FromEnvVar for tracing::Level { - type Error = LevelParseError; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { 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) + .map_err(LevelParseError::from) + .map_err(|error| FromEnvErr::parse_error(env_var, error)) } } impl FromEnv for SignetSystemConstants { - type Error = ParseChainError; - fn inventory() -> Vec<&'static EnvItemInfo> { vec![&EnvItemInfo { var: "CHAIN_NAME", @@ -682,7 +600,7 @@ impl FromEnv for SignetSystemConstants { }] } - fn from_env() -> Result> { + fn from_env() -> Result { SignetSystemConstants::from_env_var("CHAIN_NAME") } } @@ -700,15 +618,6 @@ mod test { std::env::set_var(env, val.to_string()); } - fn load_expect_err(env: &str, err: FromEnvErr) - where - T: FromEnvVar, - T::Error: PartialEq, - { - let res = T::from_env_var(env).unwrap_err(); - assert_eq!(res, err); - } - fn test(env: &str, val: T) where T: ToString + FromEnvVar + PartialEq + std::fmt::Debug, @@ -719,16 +628,6 @@ mod test { assert_eq!(res, val); } - fn test_expect_err(env: &str, value: U, err: FromEnvErr) - where - T: FromEnvVar, - U: ToString, - T::Error: PartialEq, - { - set(env, &value); - load_expect_err::(env, err); - } - #[test] fn test_primitives() { test("U8", 42u8); @@ -762,13 +661,13 @@ mod test { #[test] fn test_a_few_errors() { - test_expect_err::( - "U8_", - 30000u16, - FromEnvErr::parse_error("30000".parse::().unwrap_err()), - ); + set("U8_", &30000u16); + let err = u8::from_env_var("U8_").unwrap_err(); + assert!(matches!(err, FromEnvErr::ParseError(ref var, _) if var == "U8_")); - test_expect_err::("U8_", "", FromEnvErr::empty("U8_")); + set("U8_", &""); + let err = u8::from_env_var("U8_").unwrap_err(); + assert!(matches!(err, FromEnvErr::Empty(ref var) if var == "U8_")); } #[test] diff --git a/src/utils/metrics.rs b/src/utils/metrics.rs index 5fabb10..7d10cf1 100644 --- a/src/utils/metrics.rs +++ b/src/utils/metrics.rs @@ -41,8 +41,6 @@ impl From for MetricsConfig { } impl FromEnv for MetricsConfig { - type Error = std::num::ParseIntError; - fn inventory() -> Vec<&'static EnvItemInfo> { vec![&EnvItemInfo { var: METRICS_PORT, @@ -51,7 +49,7 @@ impl FromEnv for MetricsConfig { }] } - fn from_env() -> Result> { + fn from_env() -> Result { match u16::from_env_var(METRICS_PORT).map(Self::from) { Ok(cfg) => Ok(cfg), Err(_) => Ok(Self::default()), diff --git a/src/utils/otlp.rs b/src/utils/otlp.rs index ccdb163..fe48af3 100644 --- a/src/utils/otlp.rs +++ b/src/utils/otlp.rs @@ -84,8 +84,6 @@ pub struct OtelConfig { } impl FromEnv for OtelConfig { - type Error = url::ParseError; - fn inventory() -> Vec<&'static EnvItemInfo> { vec![ &EnvItemInfo { @@ -107,7 +105,7 @@ impl FromEnv for OtelConfig { ] } - fn from_env() -> Result> { + fn from_env() -> Result { // load endpoint from env. ignore empty values (shortcut return None), parse, and print the error if any using inspect_err let endpoint = Url::from_env_var(OTEL_ENDPOINT)?; diff --git a/src/utils/provider.rs b/src/utils/provider.rs index a20eb98..e00f883 100644 --- a/src/utils/provider.rs +++ b/src/utils/provider.rs @@ -39,11 +39,11 @@ impl From for ProviderConnectError { } impl FromEnvVar for BuiltInConnectionString { - type Error = ProviderConnectError; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { let conn_str = String::from_env_var(env_var).map_err(FromEnvErr::infallible_into)?; - let built_in = conn_str.parse().map_err(ProviderConnectError::from)?; + let built_in = conn_str + .parse() + .map_err(|error| FromEnvErr::parse_error(env_var, ProviderConnectError::from(error)))?; Ok(built_in) } } @@ -72,9 +72,7 @@ impl ProviderConfig { } impl FromEnvVar for ProviderConfig { - type Error = ProviderConnectError; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { let connection_string = BuiltInConnectionString::from_env_var(env_var)?; Ok(Self { connection_string }) } @@ -126,11 +124,9 @@ impl TryFrom for PubSubConfig { } impl FromEnvVar for PubSubConfig { - type Error = ProviderConnectError; - - fn from_env_var(env_var: &str) -> Result> { + fn from_env_var(env_var: &str) -> Result { let cs = BuiltInConnectionString::from_env_var(env_var)?; - Self::try_from(cs).map_err(FromEnvErr::ParseError) + Self::try_from(cs).map_err(|error| FromEnvErr::parse_error(env_var, error)) } }