oxidecomputer / oxidecomputer/typify

Getting empty enum with allOf of oneOfs

Open
#897 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
898
Forks
114
Avg merge
4h 18m
Merged PRs (30d)
14

Description

Getting empty enum with allOfs of oneOfs

For this schema:

{
  "openapi": "3.0.0",
  "info": {
    "title": "NEAR Protocol JSON RPC API",
    "version": "1.1.2"
  },
  "paths": {},
  "components": {
    "schemas": {
      "MyStruct": {
        "allOf": [
          {
            "oneOf": [
              {
                "properties": {
                  "myfirsttag": {
                    "enum": [
                      "a"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "myfirsttag"
                ],
                "type": "object"
              },
              {
                "format": "uint64",
                "minimum": 0,
                "properties": {
                  "myfirsttag": {
                    "enum": [
                      "b"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "myfirsttag"
                ],
                "type": "object"
              }
            ]
          },
          {
            "oneOf": [
              {
                "properties": {
                  "mysecondtag": {
                    "enum": [
                      "c"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "mysecondtag"
                ],
                "type": "object"
              },
              {
                "format": "uint64",
                "minimum": 0,
                "properties": {
                  "mysecondtag": {
                    "enum": [
                      "d"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "mysecondtag"
                ],
                "type": "object"
              }
            ]
          }
        ],
        "title": "MyStruct",
        "type": "object"
      }
    }
  }
}

The output is:

    #[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
    #[serde(untagged)]
    pub enum MyStruct {
        Variant0(MyStructVariant0),
        Variant1(MyStructVariant1),
    }

    #[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
    #[serde(untagged)]
    pub enum MyStructVariant0 {
        Variant0(MyStructVariant0Variant0),
        Variant1(MyStructVariant0Variant1),
    }

    #[serde(deny_unknown_fields)]
    pub enum MyStructVariant0Variant0 {}

There was a similar issue https://github.com/oxidecomputer/typify/issues/829 which was successfully fixed. This thing is a more advanced.

@ahl here you mention the ongoing work "to separate out schema processing such as merging schemas". Is that going to help?

Use serde(flatten) whenever possible

I would create a second issue out of that for the following. But let it be here for now. I put it here as it may be connected
The previous schema is actually created from the rust code with schemars:

#[derive(JsonSchema)]
struct MyStruct {
    #[serde(flatten)]
    pub first_enum: MyFirstEnum,
    #[serde(flatten)]
    pub second_enum: MySecondEnum,
}

#[derive(JsonSchema)]
#[serde(tag = "myfirsttag", rename_all = "snake_case")]
enum MyFirstEnum {
    A(String),
    B(u64)
}

#[derive(JsonSchema)]
#[serde(tag = "mysecondtag", rename_all = "snake_case")]
enum MySecondEnum {
    C(String),
    D(u64)
}

So after that, I would say "let's use serde(flatten) whenever it's possible". For this case, it sounds reasonable. Firstly, it deduplicates the code. Secondly, it helps with naming. Though I am not sure if it's reasonable for the general case.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the schema-processing and schema-merging work referenced in issue 856, and compare the related fix in issue 829 against the provided MyStruct schema and generated Rust output. Done means this allOf/oneOf combination no longer produces an empty enum, with serde(flatten) used where the resulting representation permits it.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.