For your case @JeremyMeadows answer is probably the best.
But in general, if you want to keep the error, you could do something like:
let length: usize = std::env::var("LENGTH")
.map_err(Box::<dyn std::error::Error>::from)
.and_then(|id| id.parse::<usize>().map_err(Into::into))
.unwrap_or(8);
Or even more generic, which is probably how I would do it in my own projects:
use std::{error::Error, str::FromStr};
fn main() {
fn parse_from_env<T>(key: &str) -> Result<T, Box<dyn Error>>
where
T: FromStr,
<T as FromStr>::Err: Into<Box<dyn std::error::Error>>,
{
std::env::var(key)?.parse().map_err(Into::into)
}
let length: usize = parse_from_env("LENGTH").unwrap_or(8);
}
Or, if my project was more professional:
use std::{error::Error, str::FromStr};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyErrors {
#[error("unable to read environment variable")]
EnvNotValid(#[source] Box<dyn Error>),
}
fn main() {
fn parse_from_env<T>(key: &str) -> Result<T, MyErrors>
where
T: FromStr,
<T as FromStr>::Err: Into<Box<dyn std::error::Error>>,
{
std::env::var(key)
.map_err(|e| MyErrors::EnvNotValid(e.into()))?
.parse()
.map_err(|e: <T as FromStr>::Err| MyErrors::EnvNotValid(e.into()))
}
let length: usize = parse_from_env("LENGTH").unwrap_or(8);
}