Skip to content

Commit

Permalink
Add decimal_float feature. (#750)
Browse files Browse the repository at this point in the history
This feature aim to provide utoipa user's the ability to change the default type for Decimal to Number without the need of overriding the type everywhere much like rust_decimal expose an serde-with-float feature.
This feature is mutually exclusive with `decimal` feature.
  • Loading branch information
Romain Lebran authored Sep 5, 2023
1 parent 1443ec4 commit b1ce2d0
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ and the `ipa` is _api_ reversed. Aaand... `ipa` is also an awesome type of beer
- **decimal** Add support for [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` type. **By default**
it is interpreted as `String`. If you wish to change the format you need to override the type.
See the `value_type` in [component derive docs](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html).
- **decimal_float** Add support for [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` type. **By default**
it is interpreted as `Number`. This feature is mutually exclusive with **decimal** and allow to change the default type used in your
documentation for `Decimal` much like `serde_with_float` feature exposed by rust_decimal.
- **uuid** Add support for [uuid](https://github.com/uuid-rs/uuid). `Uuid` type will be presented as `String` with
format `uuid` in OpenAPI spec.
- **ulid** Add support for [ulid](https://github.com/dylanhart/ulid-rs). `Ulid` type will be presented as `String` with
Expand Down
1 change: 1 addition & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ if [[ "$crate" == "utoipa" ]]; then
elif [[ "$crate" == "utoipa-gen" ]]; then
cargo test -p utoipa-gen --features utoipa/actix_extras,chrono,decimal,utoipa/uuid,uuid,utoipa/ulid,ulid,utoipa/url,url,utoipa/time,time,utoipa/repr,utoipa/smallvec,smallvec,rc_schema,utoipa/rc_schema

cargo test -p utoipa-gen --test schema_derive_test --features decimal_float
cargo test -p utoipa-gen --test path_derive_auto_into_responses --features auto_into_responses,utoipa/uuid,uuid
cargo test -p utoipa-gen --test path_derive_actix --test path_parameter_derive_actix --features actix_extras,utoipa/uuid,uuid
cargo test -p utoipa-gen --test path_derive_auto_into_responses_actix --features actix_extras,utoipa/auto_into_responses,utoipa/uuid,uuid
Expand Down
1 change: 1 addition & 0 deletions utoipa-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ actix_extras = ["regex", "syn/extra-traits"]
chrono = []
yaml = []
decimal = []
decimal_float = []
rocket_extras = ["regex", "syn/extra-traits"]
non_strict_integers = []
uuid = ["dep:uuid"]
Expand Down
3 changes: 3 additions & 0 deletions utoipa-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#![warn(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]

#[cfg(all(feature = "decimal", feature = "decimal_float"))]
compile_error!("`decimal` and `decimal_float` are mutually exclusive feature flags");

use std::{mem, ops::Deref};

use component::schema::Schema;
Expand Down
19 changes: 17 additions & 2 deletions utoipa-gen/src/schema_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl SchemaType<'_> {
#[cfg(not(any(
feature = "chrono",
feature = "decimal",
feature = "decimal_float",
feature = "rocket_extras",
feature = "uuid",
feature = "ulid",
Expand All @@ -45,6 +46,7 @@ impl SchemaType<'_> {
#[cfg(any(
feature = "chrono",
feature = "decimal",
feature = "decimal_float",
feature = "rocket_extras",
feature = "uuid",
feature = "ulid",
Expand All @@ -59,7 +61,7 @@ impl SchemaType<'_> {
primitive = is_primitive_chrono(name);
}

#[cfg(feature = "decimal")]
#[cfg(any(feature = "decimal", feature = "decimal_float"))]
if !primitive {
primitive = is_primitive_rust_decimal(name);
}
Expand Down Expand Up @@ -172,7 +174,7 @@ fn is_primitive_chrono(name: &str) -> bool {
}

#[inline]
#[cfg(feature = "decimal")]
#[cfg(any(feature = "decimal", feature = "decimal_float"))]
fn is_primitive_rust_decimal(name: &str) -> bool {
matches!(name, "Decimal")
}
Expand Down Expand Up @@ -206,6 +208,9 @@ impl ToTokens for SchemaType<'_> {
#[cfg(feature = "decimal")]
"Decimal" => tokens.extend(quote! { utoipa::openapi::SchemaType::String }),

#[cfg(feature = "decimal_float")]
"Decimal" => tokens.extend(quote! { utoipa::openapi::SchemaType::Number }),

#[cfg(feature = "rocket_extras")]
"PathBuf" => tokens.extend(quote! { utoipa::openapi::SchemaType::String }),

Expand Down Expand Up @@ -283,6 +288,7 @@ impl Type<'_> {

#[cfg(not(any(
feature = "chrono",
feature = "decimal_float",
feature = "uuid",
feature = "ulid",
feature = "url",
Expand All @@ -294,6 +300,7 @@ impl Type<'_> {

#[cfg(any(
feature = "chrono",
feature = "decimal_float",
feature = "uuid",
feature = "ulid",
feature = "url",
Expand All @@ -307,6 +314,11 @@ impl Type<'_> {
known_format = matches!(name, "DateTime" | "Date" | "NaiveDate" | "NaiveDateTime");
}

#[cfg(feature = "decimal_float")]
if !known_format {
known_format = matches!(name, "Decimal");
}

#[cfg(feature = "uuid")]
if !known_format {
known_format = matches!(name, "Uuid");
Expand Down Expand Up @@ -387,6 +399,9 @@ impl ToTokens for Type<'_> {
#[cfg(any(feature = "chrono", feature = "time"))]
"Date" => tokens.extend(quote! { utoipa::openapi::SchemaFormat::KnownFormat(utoipa::openapi::KnownFormat::Date) }),

#[cfg(any(feature = "decimal_float"))]
"Decimal" => tokens.extend(quote! { utoipa::openapi::SchemaFormat::KnownFormat(utoipa::openapi::KnownFormat::Double) }),

#[cfg(feature = "uuid")]
"Uuid" => tokens.extend(quote! { utoipa::openapi::SchemaFormat::KnownFormat(utoipa::openapi::KnownFormat::Uuid) }),

Expand Down
41 changes: 41 additions & 0 deletions utoipa-gen/tests/schema_derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3131,6 +3131,47 @@ fn derive_struct_with_rust_decimal_with_type_override() {
}
}

#[cfg(feature = "decimal_float")]
#[test]
fn derive_struct_with_rust_decimal_float() {
use rust_decimal::Decimal;

let post = api_doc! {
struct Post {
id: i32,
rating: Decimal,
}
};

assert_value! {post=>
"properties.id.type" = r#""integer""#, "Post id type"
"properties.id.format" = r#""int32""#, "Post id format"
"properties.rating.type" = r#""number""#, "Post rating type"
"properties.rating.format" = r#""double""#, "Post rating format"
}
}

#[cfg(feature = "decimal_float")]
#[test]
fn derive_struct_with_rust_decimal_float_with_type_override() {
use rust_decimal::Decimal;

let post = api_doc! {
struct Post {
id: i32,
#[schema(value_type = String)]
rating: Decimal,
}
};

assert_value! {post=>
"properties.id.type" = r#""integer""#, "Post id type"
"properties.id.format" = r#""int32""#, "Post id format"
"properties.rating.type" = r#""string""#, "Post rating type"
"properties.rating.format" = r#"null"#, "Post rating format"
}
}

#[cfg(feature = "uuid")]
#[test]
fn derive_struct_with_uuid_type() {
Expand Down
1 change: 1 addition & 0 deletions utoipa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ rocket_extras = ["utoipa-gen/rocket_extras"]
axum_extras = ["utoipa-gen/axum_extras"]
chrono = ["utoipa-gen/chrono"]
decimal = ["utoipa-gen/decimal"]
decimal_float = ["utoipa-gen/decimal_float"]
non_strict_integers = ["utoipa-gen/non_strict_integers"]
yaml = ["serde_yaml", "utoipa-gen/yaml"]
uuid = ["utoipa-gen/uuid"]
Expand Down
3 changes: 3 additions & 0 deletions utoipa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
//! * **decimal** Add support for [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` type. **By default**
//! it is interpreted as `String`. If you wish to change the format you need to override the type.
//! See the `value_type` in [`ToSchema` derive docs][to_schema_derive].
//! * **decimal_float** Add support for [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` type. **By default**
//! it is interpreted as `Number`. This feature is mutually exclusive with **decimal** and allow to change the default type used in your
//! documentation for `Decimal` much like `serde_with_float` feature exposed by rust_decimal.
//! * **uuid** Add support for [uuid](https://github.com/uuid-rs/uuid). `Uuid` type will be presented as `String` with
//! format `uuid` in OpenAPI spec.
//! * **ulid** Add support for [ulid](https://github.com/dylanhart/ulid-rs). `Ulid` type will be presented as `String` with
Expand Down

0 comments on commit b1ce2d0

Please sign in to comment.