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

Add schemars::JsonSchema derives to all types #347

Merged
merged 24 commits into from
May 16, 2024
Merged

Conversation

leighmcculloch
Copy link
Member

@leighmcculloch leighmcculloch commented Mar 4, 2024

What

Add schemars::JsonSchema derives to all types

Why

See stellar/xdrgen#193.

Close #348

Todo

@willemneal
Copy link
Member

@leighmcculloch I updated #349

Feel free to move the impls where ever you think is best, I'm pretty happy with them now. The next issue is enum representations. See here the option is unnamed Option 1 and the current doc strings are redundant.

Here is the site where you can view the forms generated by the schema: https://rjsf-team.github.io/react-jsonschema-form/

Unfortunately you can't share an example prefilled in, but here is a picture of the memo section of the transaction envelope.

image
  "Memo": {
    "description": "Memo is an XDR Union defines as:\n\n```text union Memo switch (MemoType type) { case MEMO_NONE: void; case MEMO_TEXT: string text<28>; case MEMO_ID: uint64 id; case MEMO_HASH: Hash hash; // the hash of what to pull from the content server case MEMO_RETURN: Hash retHash; // the hash of the tx you are rejecting }; ```",
"oneOf": [
    {
      "type": "string",
      "enum": [
        "none"
      ]
    },
    {
      "type": "object",
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string",
          "maxLength": 28
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": [
        "hash"
      ],
      "properties": {
        "hash": {
          "$ref": "#/definitions/Hash"
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": [
        "return"
      ],
      "properties": {
        "return": {
          "$ref": "#/definitions/Hash"
        }
      },
      "additionalProperties": false
    }
  ]
}

@willemneal
Copy link
Member

Oh one other thing to note are byte arrays. Currently they are treated as Vec<u8>, but a base64 string would work better for JSON. Now it's pretty painful. Here is a Hash type with one input per 32 bytes.
image

@leighmcculloch
Copy link
Member Author

Byte arrays are rendered in the JSON as hex, not as arrays, so I'm surprised the JSON schema is rendering that as an array.

@willemneal
Copy link
Member

I update BytesM to use a hex string, but pub struct Hash(pub [u8; 32]) is a default impl of schemars which is the same as Vec<u8> with a fixed length.

@leighmcculloch
Copy link
Member Author

leighmcculloch commented Mar 5, 2024

Interesting. Hash does render to hex because it has the below custom serialize/deserialize based on the display and fromstr impls:

#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(
        serde_with::SerializeDisplay,
        serde_with::DeserializeFromStr
    )
)]
pub struct Hash(pub [u8; 32]);
impl core::fmt::Display for Hash {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}
#[cfg(feature = "alloc")]
impl core::str::FromStr for Hash {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}

@willemneal
Copy link
Member

The JsonSchema type is implemented for arrays here: https://github.com/GREsau/schemars/blob/e04e3a3a8191bac1f218539733110fcc26bdbf7c/schemars/src/json_schema_impls/array.rs#L31

Not sure how to get around other than manually implementing Hash?

@leighmcculloch
Copy link
Member Author

leighmcculloch commented Mar 5, 2024

Not sure how to get around other than manually implementing Hash?

Yup, I think we can generate the manual impl in xdrgen for any type that we generate hex encoding for.

@leighmcculloch leighmcculloch marked this pull request as ready for review May 16, 2024 01:59
@leighmcculloch leighmcculloch added this pull request to the merge queue May 16, 2024
Merged via the queue into main with commit 89a8bcd May 16, 2024
10 checks passed
@leighmcculloch leighmcculloch deleted the rust-add-schemas branch May 16, 2024 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add capability to generate JSON schema for JSON repr of types
3 participants