SergioBenitez / Figment

A hierarchical configuration library so con-free, it's unreal.
Apache License 2.0
584 stars 33 forks source link

Add custom parser support to Env provider #119

Open felipou opened 3 weeks ago

felipou commented 3 weeks ago

Hi! First of all, thanks for this awesome crate!

I wanted some flexibility in the format of the environment variable values when using the Env provider, so I did a little experiment, and it seems it would be easy to implement an option to setup a custom parser in the Env provider:

https://github.com/felipou/Figment/commit/67e05517ff66903582bc69d41a1e1b79773d4da1

It needs some work, but in the tests you can see how we could easily support YAML or JSON values for example, and it would be optional, without breaking compatibility.

Does this feature make sense? Should I polish it and create a pull request?

SergioBenitez commented 3 weeks ago

Yeah! That's totally useful. Please do!

felipou commented 3 weeks ago

Great! I'll add proper documentation to the new parser method (any other suggestions for that name? I'm not totally convinced it's a good option) and some more tests.

Also, I was in doubt about what I did to the cloneable_fn_trait macro (by the way, very clever solution to the clonable box dyn), do you have any other suggestions as to what to do there? Basically the Cloneable trait which is created by this macro caused a conflict when using the macro twice, so I added the custom name for that trait as an option to the macro, but what I really wanted was to have just one trait declared, and reused... as I've written this, now I'm thinking of decomposing that macro and have one that just assumes there is an existing Cloneable trait in scope already. I'll experiment with this!

SergioBenitez commented 3 weeks ago

Basically the Cloneable trait which is created by this macro caused a conflict when using the macro twice,

You can invoke the macro inside of a module to give the resulting items different namespaces:

mod foo {
    crate::util::cloneable_fn_trait!(..);
}

mod bar {
    crate::util::cloneable_fn_trait!(..);
}
felipou commented 2 weeks ago

I actually tried that before, but it didn't work because the trait is not public, so I'm thinking of just adding the pub option to the macro?

@@ -327,6 +327,11 @@ macro_rules! make_cloneable {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! cloneable_fn_trait {
+    (pub $Name:ident: $($rest:tt)*) => {
+        pub trait $Name: $($rest)* + Cloneable + 'static { }
+        impl<F: Clone + 'static> $Name for F where F: $($rest)* { }
+        $crate::make_cloneable!($Name: Cloneable);
+    };
     ($Name:ident: $($rest:tt)*) => {
         trait $Name: $($rest)* + Cloneable + 'static { }
         impl<F: Clone + 'static> $Name for F where F: $($rest)* { }

I actually just tried this, and it worked well, I'll create the PR as soon as I finish documenting the "parser" method.

felipou commented 1 week ago

Just created the PR: https://github.com/SergioBenitez/Figment/pull/121