Skip to content

[FEATURE] Support non-object model types for Rust #2355

@jadinm

Description

@jadinm

Why do we need this improvement?

Typescript already has a TypeRenderer. The goal of the requested feature is to provide an equivalent for Rust.

You can check the output models by pasting the following model in https://modelina.org/playground

{
  "openapi": "3.1.0",
  "info": {
    "version": "0.1",
    "title": "Example."
  },
  "paths": {
    "/example": {
      "get": {
        "parameters": [
          {
            "in": "path",
            "name": "integerParam",
            "schema": {
              "type": "integer",
              "format": "int64",
              "title": "integerParam"
            },
            "required": true,
            "description": "An example of integer parameter"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "title": "ArrayReturn",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Currently, if I try to generate a crate from this spec, it will generate an invalid crate.
The lib.rs file is:

#[macro_use]
extern crate serde;
extern crate serde_json;

pub mod array_return;
pub use self::array_return::*;

pub mod integer_param;
pub use self::integer_param::*;

But the files array_return.rs and integer_param.rs aren't created.

How will this change help?

Adding a non-empty model rendering would fix the invalid generated crate issue.

Screenshots

No response

How could it be implemented/designed?

I suggest to add a new renderer (& preset) leveraging the New Type idiom of Rust: https://doc.rust-lang.org/rust-by-example/generics/new_types.html

The new rendering would be something along the lines of

return `${doc}
${structMacro}
pub struct ${this.model.name}(pub ${wrappedType});
${additionalContent}
`;

and produce the following rust code

// ArrayReturn represents a ArrayReturn model.
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct ArrayReturn(pub Vec<String>);
// IntegerParam represents a IntegerParam model.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct IntegerParam(pub i64);

Note that an alternative to the New Type idiom is to use type aliases. There are two main advantages to using the New Type idiom: compile-time value type validation and a bypass of the rust orphan rule (see https://effective-rust.com/newtype.html).

The second advantage will be needed to implement model validation. Likely this validation will come from an external trait. Rust only allows adding external trait implementations to types that are internal to the crate (type aliases do not count).

🚧 Breaking changes

No

👀 Have you checked for similar open issues?

  • I checked and didn't find a similar issue

🏢 Have you read the Contributing Guidelines?

Are you willing to work on this issue?

Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions