Skip to content

Commit

Permalink
Add macros feature flag (#1015)
Browse files Browse the repository at this point in the history
Add macros feature flag what adds separation between `utoipa` and
`utoipa-gen`. This enables better build speed in crates where
`utoipa-gen` is not necessary such as libs that only define `utoipa`
types.

The `macros` feature flag is enabled by default.
  • Loading branch information
juhaku committed Sep 1, 2024
1 parent 8948d34 commit 11c909b
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 48 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ and the `ipa` is _api_ reversed. Aaand... `ipa` is also an awesome type of beer

## Crate Features

- **`macros`** Enable `utoipa-gen` macros. **This is enabled by default.**
- **`yaml`**: Enables **serde_yaml** serialization of OpenAPI objects.
- **`actix_extras`**: Enhances [actix-web](https://github.com/actix/actix-web/) integration with being able to
parse `path`, `path` and `query` parameters from actix web path attribute macros. See
Expand Down
2 changes: 1 addition & 1 deletion scripts/doc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
# Generate utoipa workspace docs

cargo +nightly doc -Z unstable-options --workspace --no-deps \
--features actix_extras,openapi_extensions,yaml,uuid,ulid,url,non_strict_integers,actix-web,axum,rocket \
--features actix_extras,openapi_extensions,yaml,uuid,ulid,url,non_strict_integers,actix-web,axum,rocket,macros \
--config 'build.rustdocflags = ["--cfg", "doc_cfg"]'
28 changes: 14 additions & 14 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ for crate in $crates; do
echo "Testing crate: $crate..."

if [[ "$crate" == "utoipa" ]]; then
$CARGO test -p utoipa --features openapi_extensions,preserve_order,preserve_path_order,debug
$CARGO test -p utoipa --features openapi_extensions,preserve_order,preserve_path_order,debug,macros
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 --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,utoipa/macros
$CARGO test -p utoipa-gen --test schema_derive_test --features decimal_float,utoipa/macros

$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,utoipa/chrono,chrono,utoipa/time,time
$CARGO test -p utoipa-gen --test path_derive_auto_into_responses_actix --features actix_extras,utoipa/auto_into_responses,utoipa/uuid,uuid
$CARGO test -p utoipa-gen --test path_derive_auto_into_responses --features auto_into_responses,utoipa/uuid,uuid,utoipa/macros
$CARGO test -p utoipa-gen --test path_derive_actix --test path_parameter_derive_actix --features actix_extras,utoipa/uuid,uuid,utoipa/chrono,chrono,utoipa/time,time,utoipa/macros
$CARGO test -p utoipa-gen --test path_derive_auto_into_responses_actix --features actix_extras,utoipa/auto_into_responses,utoipa/uuid,uuid,utoipa/macros

$CARGO test -p utoipa-gen --test path_derive_rocket --features rocket_extras
$CARGO test -p utoipa-gen --test path_derive_rocket --features rocket_extras,utoipa/macros

$CARGO test -p utoipa-gen --test path_derive_axum_test --features axum_extras
$CARGO test -p utoipa-gen --test path_derive_auto_into_responses_axum --features axum_extras,utoipa/auto_into_responses
$CARGO test -p utoipa-gen --test path_derive_axum_test --features axum_extras,utoipa/macros
$CARGO test -p utoipa-gen --test path_derive_auto_into_responses_axum --features axum_extras,utoipa/auto_into_responses,utoipa/macros
elif [[ "$crate" == "utoipa-swagger-ui" ]]; then
$CARGO test -p utoipa-swagger-ui --features actix-web,rocket,axum
$CARGO test -p utoipa-swagger-ui --features actix-web,rocket,axum,utoipa/macros
elif [[ "$crate" == "utoipa-redoc" ]]; then
$CARGO test -p utoipa-redoc --features actix-web,rocket,axum
$CARGO test -p utoipa-redoc --features actix-web,rocket,axum,utoipa/macros
elif [[ "$crate" == "utoipa-rapidoc" ]]; then
$CARGO test -p utoipa-rapidoc --features actix-web,rocket,axum
$CARGO test -p utoipa-rapidoc --features actix-web,rocket,axum,utoipa/macros
elif [[ "$crate" == "utoipa-scalar" ]]; then
$CARGO test -p utoipa-scalar --features actix-web,rocket,axum
$CARGO test -p utoipa-scalar --features actix-web,rocket,axum,utoipa/macros
elif [[ "$crate" == "utoipa-axum" ]]; then
$CARGO test -p utoipa-axum --features debug,utoipa/debug
$CARGO test -p utoipa-axum --features debug,utoipa/debug,utoipa/macros
fi
done
1 change: 0 additions & 1 deletion utoipa-axum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ debug = []
[dependencies]
axum = { version = "0.7", default-features = false }
utoipa = { version = "5.0.0-alpha", path = "../utoipa", default-features = false }
async-trait = "0.1"
tower-service = "0.3"
tower-layer = "0.3.2"
paste = "1.0"
Expand Down
1 change: 1 addition & 0 deletions utoipa-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! of the library documentation is available through **utoipa** library itself.
//! Consider browsing via the **utoipa** crate so all links will work correctly.

#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![warn(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]

Expand Down
2 changes: 1 addition & 1 deletion utoipa-rapidoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rustdoc-args = ["--cfg", "doc_cfg"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
utoipa = { version = "5.0.0-alpha", path = "../utoipa" }
utoipa = { version = "5.0.0-alpha", path = "../utoipa", default-features = false }
actix-web = { version = "4", optional = true, default-features = false }
rocket = { version = "0.5", features = ["json"], optional = true }
axum = { version = "0.7", default-features = false, features = ["json"], optional = true }
Expand Down
4 changes: 2 additions & 2 deletions utoipa-redoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ rustdoc-args = ["--cfg", "doc_cfg"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
utoipa = { version = "5.0.0-alpha", path = "../utoipa" }
actix-web = { version = "4", optional = true, default-features = false }
utoipa = { version = "5.0.0-alpha", path = "../utoipa", default-features = false }
actix-web = { version = "4", optional = true }
rocket = { version = "0.5", features = ["json"], optional = true }
axum = { version = "0.7", default-features = false, optional = true }

Expand Down
2 changes: 1 addition & 1 deletion utoipa-scalar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rustdoc-args = ["--cfg", "doc_cfg"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
utoipa = { version = "5.0.0-alpha.0", path = "../utoipa" }
utoipa = { version = "5.0.0-alpha.0", path = "../utoipa", default-features = false }
actix-web = { version = "4", optional = true, default-features = false }
rocket = { version = "0.5", features = ["json"], optional = true }
axum = { version = "0.7", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion utoipa-swagger-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ rocket = { version = "0.5", features = ["json"], optional = true }
axum = { version = "0.7", default-features = false, features = [
"json",
], optional = true }
utoipa = { version = "5.0.0-alpha", path = "../utoipa" }
utoipa = { version = "5.0.0-alpha", path = "../utoipa", default-features = false }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }

Expand Down
43 changes: 22 additions & 21 deletions utoipa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,44 @@ rust-version.workspace = true

[features]
# See README.md for list and explanations of features
default = []
debug = ["utoipa-gen/debug"]
actix_extras = ["utoipa-gen/actix_extras"]
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"]
ulid = ["utoipa-gen/ulid"]
url = ["utoipa-gen/url"]
time = ["utoipa-gen/time"]
smallvec = ["utoipa-gen/smallvec"]
indexmap = ["utoipa-gen/indexmap"]
default = ["macros"]
debug = ["utoipa-gen?/debug"]
actix_extras = ["utoipa-gen?/actix_extras"]
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"]
ulid = ["utoipa-gen?/ulid"]
url = ["utoipa-gen?/url"]
time = ["utoipa-gen?/time"]
smallvec = ["utoipa-gen?/smallvec"]
indexmap = ["utoipa-gen?/indexmap"]
openapi_extensions = []
repr = ["utoipa-gen/repr"]
repr = ["utoipa-gen?/repr"]
preserve_order = []
preserve_path_order = []
rc_schema = ["utoipa-gen/rc_schema"]
rc_schema = ["utoipa-gen?/rc_schema"]
macros = ["dep:utoipa-gen"]

# EXPERIEMENTAL! use with cauntion
auto_into_responses = ["utoipa-gen/auto_into_responses"]
auto_into_responses = ["utoipa-gen?/auto_into_responses"]

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
serde_yaml = { version = "0.9", optional = true }
utoipa-gen = { version = "5.0.0-alpha.2", path = "../utoipa-gen" }
utoipa-gen = { version = "5.0.0-alpha.2", path = "../utoipa-gen", optional = true }
indexmap = { version = "2", features = ["serde"] }

[dev-dependencies]
assert-json-diff = "2"

[package.metadata.docs.rs]
features = ["actix_extras", "non_strict_integers", "openapi_extensions", "uuid", "ulid", "url", "yaml"]
features = ["actix_extras", "non_strict_integers", "openapi_extensions", "uuid", "ulid", "url", "yaml", "macros"]
rustdoc-args = ["--cfg", "doc_cfg"]

[lints.rust]
Expand Down
46 changes: 40 additions & 6 deletions utoipa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@

pub mod openapi;

use std::collections::{BTreeMap, HashMap};
use std::collections::BTreeMap;

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
pub use utoipa_gen::*;

/// Trait for implementing OpenAPI specification in Rust.
Expand Down Expand Up @@ -424,6 +426,8 @@ macro_rules! impl_partial_schema {
impl_partial_schema!( @impl_schema &$ty );
};
( @impl_schema $( $tt:tt )* ) => {
#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl PartialSchema for $($tt)* {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!( $($tt)* ).into()
Expand All @@ -441,14 +445,16 @@ macro_rules! impl_partial_schema_primitive {
// Create `utoipa` module so we can use `utoipa-gen` directly from `utoipa` crate.
// ONLY for internal use!
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
mod utoipa {
pub use super::*;
}

/// Trait used to implement only _`Schema`_ part of the OpenAPI doc.
///
/// This trait is by default implemented for Rust [`primitive`][primitive] types and some well known types like
/// [`Vec`], [`Option`], [`HashMap`] and [`BTreeMap`]. The default implementation adds `schema()`
/// [`Vec`], [`Option`], [`std::collections::HashMap`] and [`BTreeMap`]. The default implementation adds `schema()`
/// method to the implementing type allowing simple conversion of the type to the OpenAPI Schema
/// object. Moreover this allows handy way of constructing schema objects manually if ever so
/// wished.
Expand Down Expand Up @@ -525,18 +531,24 @@ impl_partial_schema_primitive!(

impl_partial_schema!(&str);

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for Vec<T> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(#[inline] Vec<T>).into()
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<Vec<T>> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(#[inline] Option<Vec<T>>).into()
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for [T] {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -547,6 +559,8 @@ impl<'__s, T: ToSchema<'__s>> PartialSchema for [T] {
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for &[T] {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -557,6 +571,8 @@ impl<'__s, T: ToSchema<'__s>> PartialSchema for &[T] {
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for &mut [T] {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -567,6 +583,8 @@ impl<'__s, T: ToSchema<'__s>> PartialSchema for &mut [T] {
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<&[T]> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -577,6 +595,8 @@ impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<&[T]> {
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<&mut [T]> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -587,12 +607,16 @@ impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<&mut [T]> {
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, T: ToSchema<'__s>> PartialSchema for Option<T> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(#[inline] Option<T>).into()
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for BTreeMap<K, V> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -603,6 +627,8 @@ impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for BTreeMap<K, V>
}
}

#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for Option<BTreeMap<K, V>> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
Expand All @@ -613,21 +639,27 @@ impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for Option<BTreeMa
}
}

impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for HashMap<K, V> {
#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for std::collections::HashMap<K, V> {
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
#[inline]
HashMap<K, V>
std::collections::HashMap<K, V>
)
.into()
}
}

impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema for Option<HashMap<K, V>> {
#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
impl<'__s, K: PartialSchema, V: ToSchema<'__s>> PartialSchema
for Option<std::collections::HashMap<K, V>>
{
fn schema() -> openapi::RefOr<openapi::schema::Schema> {
schema!(
#[inline]
Option<HashMap<K, V>>
Option<std::collections::HashMap<K, V>>
)
.into()
}
Expand Down Expand Up @@ -940,6 +972,8 @@ pub trait ToResponse<'__r> {

/// Internal dev module used internally by utoipa-gen
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "macros")))]
pub mod __dev {
use crate::{utoipa, OpenApi};

Expand Down

0 comments on commit 11c909b

Please sign in to comment.