Open polarathene opened 8 months ago
I was able to resolve the datetime error by including the toml type for it in the ParsedValue
enum, but since that'd interfere with the generic method and the feature conditional compilation, I guess I should revert the toml.rs
change.
It's Datetime is not compatible with chrono DateTime type unfortunately, at least serde doesn't recognize it for that.
This PR has been updated to also include support for formats Ron and Yaml.
Ron:
from_value
_): https://github.com/mehcode/config-rs/pull/476Yaml:
from_value
_): https://github.com/mehcode/config-rs/pull/474During the integration of Ron and Yaml into this PR (like with earlier TOML test for datetime), both failed running their tests due to the more implicit deserialization_any
used by Serde to support deserializing for the untagged enum.
Resolving requires either:
from_value()
to then handlewith
attribute to provide a custom deserializer that better guides handling of each formats' types into the expected type for config-rs
(eg: Ron Char
or Toml Datetime
conversion to String
).It's not too different from the prior approach, these types were in the formats own from_value()
method, whereas this approach better identifies when this is actually necessary. They still leverage feature toggles for conditional compilation.
For TOML with the Datetime
type that was easier to resolve thanks to the specific test failure. Ron and YAML failures were more cryptic usually, such as:
running 7 tests
test test_error_parse ... ok
test test_override_lowercase_value_for_enums ... ok
test test_override_uppercase_value_for_enums ... ok
test test_override_lowercase_value_for_struct ... ok
test test_override_uppercase_value_for_struct ... ok
test test_file ... ok
thread 'test_yaml_parsing_key' has overflowed its stack
fatal runtime error: stack overflow
error: test failed, to rerun pass `--test file_yaml`
Which IIRC I had read was due to how deserialize_any
works with the untagged enum, that is a situation of it recursively trying to resolve the enum incorrectly due to reaching a variant that references Self
and performing deserialize_any
on that and so forth.
deserialize_any
(due to untagged enum approach) won't be as performant as the previous match
statements for each individual format, but unlikely a concern for the purpose of config-rs
.Note Ron
0.9
will introduce a Bytes value variant (Vec<u8>
) for byte strings.
- I don't believe the current approach would match it? You'd get the fallback
Nil
.- Probably acceptable given it's unclear how
config-rs
would want to support that.
@matthiasbeyer this is ready for review, I know you're quite busy so here's a TLDR:
from_value()
here, this PR approach adds another level of indirection with ParsedValue
_).from_value()
method (no changes needed).For custom format support, the format
method added here, one I previously contributed (extract_root_table()
) and sometimes ParsedValue
are required to leverage it (_to call ParsedValue::deserialize(input_value)
_). This would require lib.rs
to make the module pub
, or some refactoring.
As it's all focused on using Serde with untagged enum, perhaps it shouldn't live in format.rs
if it isn't useful to other formats (not that I expect those to be contributed much).
I also need to verify an assumption that other number types like u8
would correctly be cast to u64
supported by config-rs
. Prior to this the mapping was more explicit, and I may have a misunderstanding with the untagged enum approach using deserialize_any()
this way 😅
I will also share the other formats I integrated locally, if desired they can be contributed via follow-up PR.
So from what I read, we want this in. @polarathene I'd like this PR to be rebased to latest master, so we get a CI run with latest master. After that, I think you can merge this!
After that, I think you can merge this!
I still need to address my concerns from my prior comment here. I will return to config-rs
later today or tomorrow hopefully, presently tied up elsewhere for a bit.
After that's sorted locally, I'll rebase as requested and it'd be great to see this get merged :)
Regarding custom format support, how would you approach verifying that? Mostly so that you can catch that format
module should be made public, incase someone were to revert that accidentally?
Note to self, since this PR was raised the proposed yaml alternative (serde compatible) has been archived and a different yaml crate has been introduced instead, so this PR will need to drop that support (unfortunate, since the serde approach was preferrable I think).
Inspired from the
json5
feature (Original PR July 2020, revised PR May 2021) with the refactoring in the revision by @matthiasbeyerIt looked useful for other formats that use
serde
to simplify their logic (so long as test coverage is informative of no issues 🙏 )DRY: The
json
,json5
andtoml
parsers all leverageserde
and can share a common enum to deserialize data into, instead of individual methods performing roughly the same transformations.ron
improves their support for serde untagged enums with v0.9,it is still not compatible with this approach (Their README details why).(UPDATE: At least for the currentconfig-rs
test coverage, this appears to be passing now)yaml
support doesn't leverageserde
thus is not compatible. (UPDATE: Since there is talk about the unmaintained status, it could be switched forserde-yaml
, I've verified it can pass the tests with an extra deserializer method)from_parsed_value()
is based on the approached used byformat/json5.rs
:ValueKind
enum, which could not directly be used due to theTable
andArray
types usingValue
as their value storage type instead of self-referencing the enum.impl From
, but supports the complimentaryuri
parameter for eachValue
derived.Resolves: https://github.com/mehcode/config-rs/pull/394