nested-deserialize 0.1.0

A very special-case implementation of serde::Deserialize for untagged nested enums.
Documentation
# nested-deserialize

A very special-case implementation of `serde::Deserialize` for untagged nested enums (also known as _merged enums_ or _enum unions_).

It applies to the following case:

* "Outer" enum is untagged
* Outer enum has 1-length tuple variants
* ..of which the value is an enum
  * which _should_ not have colliding variant names with its "sibling enums" used in other variants of the outer enum (also known as the term _non-overlapping_)
  * which must implement `serde::Deserialize`
    * specifically as an [externally tagged enum]https://serde.rs/enum-representations.html#externally-tagged
  * and [`strum::VariantNames`]https://docs.rs/strum/latest/strum/derive.VariantNames.html
    * where the renaming rules (if any) _must_ be in sync with serde

It effectively achieves the same as copy-pasting the variants of each inner enum into an outer enum (or using a macro to do this), and then implementing `TryFrom` for the inner enums.

## Example

```rust
use nested_deserialize::NestedDeserialize;
use strum::VariantNames;

#[derive(Deserialize, VariantNames, Debug)] // `VariantNames` required, subject to change
enum Physics {                              // "Inner" enum
    Velocity { m_s: f64 },
    Acceleration { m_s2: f64 },
}

#[derive(Deserialize, VariantNames, Debug)]
enum Chemistry {                            // "Inner" enum
    MolarMass { g_mol: f64 },
    PhValue { ph: f64 },
}

#[derive(NestedDeserialize, Debug)]         // This crate provides `NestedDeserialize`
enum ScienceData {                          // "Outer" enum
    Phys(Physics),
    Chem(Chemistry),
}
```

## Differences with other solutions

### [`#[serde(untagged)]`]https://serde.rs/enum-representations.html#untagged

* `#[serde(untagged)]` tries to parse as each variant in order
* `nested-deserialize` delegates to variants based on the tag (can only support enums)
<br/><br/>
* `#[serde(untagged)]` discards any errors from parsing as the inner variants
* `nested-deserialize` provides specialized errors for the following:
  * unknown variant (tag)
  * invalid tagged enum shape
  * the error from the variant, if a valid variant was specified, but could not be deserialized into

### [`deserialize_untagged_verbose_error`]https://crates.io/crates/deserialize_untagged_verbose_error

* `deserialize_untagged_verbose_error` tries to parse as each variant in order (like `#[serde(untagged)]`)
* `nested-deserialize` delegates to variants based on the tag (can only support enums)
<br/><br/>
* `deserialize_untagged_verbose_error` returns errors from _all variants it tried_
  * which is good for debugging
  * ..but most likely you already knew which variant you were trying to use
* `nested-deserialize` provides the error from trying to deserialize as the specified variant
  * or provides a list of valid variants if none matched
  * or provides a generic error message in case of an invalid type

### [`serde-untagged`]https://crates.io/crates/serde-untagged

* `serde-untagged` is not a proc macro
  * requires writing boilerplate
  * ultimate control
* `nested-deserialize` is a proc macro
  * apply it to an enum and done
  * may not satisfy complicated use-cases

## AI usage disclosure

I vibecoded this, it's about 150 lines of code (pretty simple), and it seems to work for the described usecase. I plan to rewrite parts if needed, by hand, once I fully understand how proc macros work. 

If you're interested in this crate/need this functionality, and willing to spend some time helping me with polishing it, please reach out to me.

## To-Do / Wishlist

* remove dependency on `strum`
* support [adjacently tagged enums]https://serde.rs/enum-representations.html#adjacently-tagged (the more popular type)
* recursive nesting