confique icon indicating copy to clipboard operation
confique copied to clipboard

Deriving `Config` for enums

Open LukasKalbertodt opened this issue 3 years ago • 5 comments

(Issue moved from here for better discussion)

@amkartashov wrote:

What about allowing to derive Config for enums? I started using your library in my project and have oneof fields described by enums. I parse it with serde fow now, so it's a mixed approach.

LukasKalbertodt avatar Oct 17 '22 16:10 LukasKalbertodt

@amkartashov could you describe your use case in more detail? Maybe some example code how you wish confique would work?

LukasKalbertodt avatar Oct 17 '22 16:10 LukasKalbertodt

Thanks @LukasKalbertodt My usecase is to support mutually exclusive sections in config file. I'm writing app which can use different backend types, so it can store blobs on a filesystem or in KV storage or something else.

In config it looks like this (filesystem as backend):

backend:
  actions:
    module: fs
    options:
      path: /tmp/cache/ac
  blobs:
    module: fs
    options:
      path: /tmp/cache/cas
      max_chunk_size: 10000000

or like this (GRPC service as backend for actions, TiKV as backend for blobs)

backend:
  actions:
    module: grpc
    options:
      url: grpc://localhost:8980
  blobs:
    module: tikv
    options:
      db_url:  ...
      max_chunk_size: 10000000

As of now, I use serde to parse config file:

#[derive(Debug, Deserialize, Config, Clone)]
pub struct Conf {
...
    #[config(nested)]
    pub backend: BackendConf,
}

#[derive(Debug, Deserialize, Config, Clone)]
pub struct BackendConf {
...
    pub actions: Option<ActionStorageConf>,
    pub blobs: Option<BlobStorageConf>,
}



#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "module", content = "options")]
pub enum ActionStorageConf {
    #[serde(alias = "fs")]
    FS(FsActionStorageConf),
   ...
}

#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "module", content = "options")]
pub enum BlobStorageConf {
    #[serde(alias = "fs")]
    FS(FsBlobStorageConf),
    ...
}

#[derive(Debug, Deserialize, Clone)]
pub struct FsActionStorageConf {
    pub path: PathBuf,
}

#[derive(Debug, Deserialize, Clone)]
pub struct FsBlobStorageConf {
    pub path: PathBuf,
    #[serde(default = "default_fs_blob_max_chunk_size")]
    pub max_chunk_size: usize,
}

amkartashov avatar Oct 18 '22 02:10 amkartashov

So basically, it works this far with serde, but I can't use confique features like using env vars for example.

amkartashov avatar Oct 18 '22 02:10 amkartashov

Thanks for the example! Seems like a useful feature to me. Is probably related to #14. I will dig into this in the future, trying to come up with a nice API. But no promises as to when. For now I'm happy with 0.2.0. Of course if you want to, you can suggest a specific way confique would derive Config for enums (as comment first, no need to implement it already).

LukasKalbertodt avatar Oct 21 '22 21:10 LukasKalbertodt

Require this (specifically tagging stuff) before I can adopt this crate. Here's some examples of our enums:

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(
    untagged,
    expecting = "expected a project name or dependency config object"
)]
pub enum ProjectDependsOn {
    String(ProjectID),
    Object(DependencyConfig),
}


#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(
    untagged,
    expecting = "expected a sequence of globs or a map of projects"
)]
pub enum WorkspaceProjects {
    Both {
        globs: Vec<FileGlob>,
        sources: ProjectsMap,
    },
    Globs(Vec<FileGlob>),
    Sources(ProjectsMap),
}

milesj avatar Mar 23 '23 19:03 milesj