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

Enums do not seem to be handled correctly by Serialized provider #32

Closed
c-x-berger opened this issue Aug 28, 2021 · 1 comment
Closed
Labels
bug Something isn't working

Comments

@c-x-berger
Copy link

c-x-berger commented Aug 28, 2021

I'm building an application (atop Rocket) with three access modes:

  • Public: Everyone has the same access to the service.
  • Privileged: Some people have more lax permissions. They submit a key to the service to show that they're a VIP or whatever.
  • Private: Only VIPs are allowed to access the service.

So we've (really @132ikl) built up a configuration structure that looks something like this:

#[derive(Serialize, Deserialize, Clone)]
struct Config {
    default_access: Access,
    mode: Mode,
}

#[derive(Serialize, Deserialize, Clone)]
enum Mode {
    Public,
    Privileged((Vec<String>, Access)),
    Private(Vec<String>),
}

/// In the Privileged case, this is probably more lax than the default_access
#[derive(Serialize, Deserialize, Clone)]
struct Access {
    max_size: u64,
    force_something: bool,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            default_access: Access {
                max_size: 4096,
                force_something: true,
            },
            mode: Mode::Private(vec!["memes lol".into()]),
        }
    }
}

So far so good. However, this appears to get... mangled when put into a figment. Here's how serde_json serializes the default value, for comparison:

{"default_access":{"max_size":4096,"force_something":true},"mode":{"Private":["memes lol"]}}

Here, mode's variant is indicated as you would expect for an enum by default in Serde.

However, if we put the same structure into a Figment with Figment::new().merge(Serialized.defaults(Config::default())), we don't seem to get the same tagging:

// from dbg!(figment)
value: Ok(
    {
        Profile(
            Uncased {
                string: "default",
            },
        ): {
            "default_access": Dict(
                Tag(Default, 1),
                {
                    "force_something": Bool(
                        Tag(Default, 1),
                        true,
                    ),
                    "max_size": Num(
                        Tag(Default, 1),
                        U64(
                            4096,
                        ),
                    ),
                },
            ),
            "mode": Array(   // Where's the enum tag?
                Tag(Default, 1),
                [
                    String(
                        Tag(Default, 1),
                        "memes lol",
                    ),
                ],
            ),
        },
    },
),

This causes problems for a Rocket application:

#[get("/")]
fn dummy() -> &'static str {
    "there's a strange dummy endpoint outside my home\n"
}

#[launch]
fn rocket() -> _ {
    let fig =
        Figment::from(rocket::Config::default()).merge(Serialized::defaults(Config::default()));
    let rocket = rocket::custom(fig)
        .mount("/", routes![dummy])
        .attach(AdHoc::config::<Config>()); // this fairing fails because...
    rocket
}
$ cargo run
Error: Rocket configuration extraction from provider failed.
   >> invalid type: found sequence, expected enum Mode
   >> for key default.mode
   >> in src/main.rs:45:56 figment_broke::Config
Error: Rocket failed to launch due to failing fairings:
   >> figment_broke::Config
@SergioBenitez SergioBenitez added the bug Something isn't working label Sep 5, 2022
@SergioBenitez
Copy link
Owner

SergioBenitez commented Sep 5, 2022

Figment isn't serializing enums correctly; this is indeed a bug! Thank you for reporting. Working on a fix now. (And apologies for getting to this so late!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants