Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
feat: add env key to error struct
Browse files Browse the repository at this point in the history
  • Loading branch information
pleshevskiy committed Dec 24, 2022
1 parent c9d8aa0 commit 0624215
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 30 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

/target

# direnv
.direnv/
.envrc
3 changes: 0 additions & 3 deletions .vim/coc-settings.json

This file was deleted.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "enve"
version = "0.3.0"
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
version = "0.4.0"
authors = ["Dmitriy Pleshevskiy <dmitriy@pleshevski.ru>"]
description = "it helps you work with environment variables and convert it to any type using only type annotations"
categories = ["config"]
keywords = ["env", "environment"]
Expand Down
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
all: test build

test:
cargo test --all-features

watch-test:
cargo watch -x 'test --all-features'

build: fmt clippy
cargo build

fmt:
cargo fmt -- --check

clippy:
cargo clippy

help:
cat Makefile
8 changes: 3 additions & 5 deletions examples/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ USAGE:
E=10+10*2-4 cargo run --example calc --all-features
";

fn main() -> Result<(), enve::Error> {
fn main() {
let res: f32 = enve::get::<Sum<PlusVec<MinusVec<Product<MulVec<f32>>>>>>("E")
.map_err(|err| {
match err {
enve::Error::NotPresent => eprintln!("The expression was not found"),
match err.reason() {
enve::Reason::NotPresent => eprintln!("The expression was not found"),
rest => eprintln!("ERROR: {}", rest),
}

Expand All @@ -26,8 +26,6 @@ fn main() -> Result<(), enve::Error> {
.agg();

println!("result: {}", res);

Ok(())
}

struct MinusVec<T>(Vec<T>);
Expand Down
43 changes: 43 additions & 0 deletions flake.lock

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

25 changes: 25 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShell = pkgs.mkShell {
packages = with pkgs; [
cargo
cargo-watch
rustc
rustfmt
clippy
rust-analyzer
];
RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
};
});
}
22 changes: 13 additions & 9 deletions src/core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::error::Error;
use crate::error::{Error, Reason};
use estring::{EString, ParseFragment, ToEString};

/// Fetches the environment variable `key` from the current process. It set value `default`
Expand All @@ -25,12 +25,14 @@ use estring::{EString, ParseFragment, ToEString};
/// }
/// ```
#[allow(clippy::needless_pass_by_value)]
pub fn get_or_set_default<R>(env_name: &str, default: R) -> Result<R, Error>
pub fn get_or_set_default<R>(key: &str, default: R) -> Result<R, Error>
where
R: ParseFragment + ToEString,
{
get::<R>(env_name).or_else(|err| match err {
Error::NotPresent => sset(env_name, default).parse().map_err(Error::from),
get::<R>(key).or_else(|err| match err.reason() {
Reason::NotPresent => sset(key, default)
.parse()
.map_err(|e| Error(key.to_string(), e.into())),
_ => Err(err),
})
}
Expand Down Expand Up @@ -64,7 +66,7 @@ pub fn get<R>(key: &str) -> Result<R, Error>
where
R: ParseFragment,
{
sget(key).and_then(|v| v.parse().map_err(Error::from))
sget(key).and_then(|v| v.parse().map_err(|e| Error(key.to_string(), e.into())))
}

/// Fetches the environment variable `key` from the current process and returns value as
Expand All @@ -90,7 +92,9 @@ where
/// }
/// ```
pub fn sget(key: &str) -> Result<EString, Error> {
std::env::var(key).map_err(Error::from).map(EString::from)
std::env::var(key)
.map_err(|e| Error(key.to_string(), e.into()))
.map(EString::from)
}

/// Sets the environment variable `key` to the value `value` for the currently running
Expand Down Expand Up @@ -154,7 +158,7 @@ mod tests {
fn should_throw_no_present_error() {
let en = TestCase::<2>.to_string();
match get::<&str>(&en) {
Err(Error::NotPresent) => {}
Err(Error(_, Reason::NotPresent)) => {}
_ => unreachable!(),
};
}
Expand Down Expand Up @@ -187,7 +191,7 @@ mod tests {
let en = TestCase::<5>.to_string();
std::env::set_var(&en, "-10");
match get::<u32>(&en) {
Err(Error::Parse(orig)) => {
Err(Error(_, Reason::Parse(orig))) => {
assert_eq!(orig, EString::from("-10"));
}
_ => unreachable!(),
Expand Down Expand Up @@ -283,7 +287,7 @@ mod tests {
let en = TestCase::<11>.to_string();
std::env::set_var(&en, "1,2,3,4,5");
match get::<SepVec<i32, '+'>>(&en) {
Err(Error::Parse(orig)) => {
Err(Error(_, Reason::Parse(orig))) => {
assert_eq!(orig, EString::from("1,2,3,4,5"));
}
_ => unreachable!(),
Expand Down
46 changes: 36 additions & 10 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,33 @@ use estring::EString;

/// The error type for operations interacting with environment variables
#[derive(Debug)]
pub enum Error {
pub struct Error(pub(crate) String, pub(crate) Reason);

impl Error {
/// Returns the environment variable name for the failure
pub fn var_name(&self) -> &str {
&self.0
}

/// Returns the reason for the failure
pub fn reason(&self) -> &Reason {
&self.1
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"The environment variable '{}' failed: {}",
self.0, self.1
)
}
}

/// The reason for the failure to get environment variable
#[derive(Debug, Clone)]
pub enum Reason {
/// The specified environment variable was not present in the current process's environment.
NotPresent,

Expand All @@ -20,16 +46,16 @@ pub enum Error {
Invalid(OsString),
}

impl fmt::Display for Error {
impl fmt::Display for Reason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
Error::NotPresent => f.write_str("The specified env variable was not present"),
Error::Invalid(inner) => write!(
Reason::NotPresent => f.write_str("The specified env variable was not present"),
Reason::Invalid(inner) => write!(
f,
"The specified env variable was found, but it did not valid: '{:?}'",
inner,
),
Error::Parse(env_name) => {
Reason::Parse(env_name) => {
write!(f, r#"Failed to parse environment variable "{}""#, env_name)
}
}
Expand All @@ -38,17 +64,17 @@ impl fmt::Display for Error {

impl error::Error for Error {}

impl From<VarError> for Error {
impl From<VarError> for Reason {
fn from(err: VarError) -> Self {
match err {
VarError::NotPresent => Error::NotPresent,
VarError::NotUnicode(inner) => Error::Invalid(inner),
VarError::NotPresent => Reason::NotPresent,
VarError::NotUnicode(inner) => Reason::Invalid(inner),
}
}
}

impl From<estring::Error> for Error {
impl From<estring::Error> for Reason {
fn from(err: estring::Error) -> Self {
Error::Parse(err.0)
Reason::Parse(err.0)
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ mod error;
mod estr;

pub use crate::core::{get, get_or_set_default, sget, sset};
pub use error::Error;
pub use error::*;
pub use estr::*;

pub use estring;

0 comments on commit 0624215

Please sign in to comment.