Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Deserializer public #78

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Make Deserializer public #78

wants to merge 1 commit into from

Conversation

Pzixel
Copy link

@Pzixel Pzixel commented Feb 21, 2025

What did you implement:

This change makes Deserializer type public. The motivation behind this is that from_env() function is too limiting and doesn't allow any control over the deserialization process.

For example consider this program:

#[derive(serde::Deserialize, Debug)]
pub struct MyEnvConfig {
    pub my_super_arr: [i32; 1],
}

// export my_super_arr=loremIpsum && cargo run
fn main() -> Result<(), Box<dyn std::error::Error>>{
    let env_config: MyEnvConfig = envy::from_env()?;
    Ok(())
}

It will exit with an error code and text

Error: Custom("invalid type: string "loremIpsum", expected an array of length 1").

However if we wrap the deserializer (which we can thanks to https://github.com/dtolnay/path-to-error ) we can get much more information about what happened:

#[derive(serde::Deserialize, Debug)]
pub struct MyEnvConfig {
    pub my_super_arr: [i32; 1],
}


fn main() -> Result<(), Box<dyn std::error::Error>>{
    let mut jd = envy::Deserializer::new(std::env::vars(), None);
    let env_config: MyEnvConfig = serde_path_to_error::deserialize(jd)?;
    Ok(())
}

Will print:

Error { path: Path { segments: [Map { key: "my_super_arr" }] }, original: Custom("invalid type: string "loremIpsum", expected an array of length 1") }

Now this is much better, because I can check the my_super_arr value.

I made this change specifically to be able to wrap into serde_path_to_error, because I have more than 100 env variables and some custom types do not mention name of the field that they failed to parse. For example primitive_types::H160 type says "expected string of length 40 but got 37". As you can imagine checking all the env strings for exact length is a very hard task.

But I think there are many other cases where wrapping the deserializer is desirable. Therefore, this type should be public

How did you verify your change:

I used my fork in my app to see if it works correctly

What (if anything) would need to be called out in the CHANGELOG for the next release:

I updated the CHANGELOG, but feel free to edit it whatever you please as I enable the "Allow edits by maintainers" checkbox.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant