chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/schemars/.cargo-checksum.json vendored Normal file

File diff suppressed because one or more lines are too long

6
vendor/schemars/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "104b0fd65055d4b46f8dcbe38cdd2ef2c4098fe2"
},
"path_in_vcs": "schemars"
}

555
vendor/schemars/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,555 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "basic-toml"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6"
dependencies = [
"serde",
]
[[package]]
name = "bigdecimal"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "bigdecimal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06619be423ea5bb86c95f087d5707942791a08a85530df0db2209a3ecfb8bc9"
dependencies = [
"autocfg",
"libm",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"num-traits",
]
[[package]]
name = "darling"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "dyn-clone"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "enumset"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
dependencies = [
"enumset_derive",
]
[[package]]
name = "enumset_derive"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
"serde",
]
[[package]]
name = "indexmap"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [
"equivalent",
"hashbrown 0.14.2",
"serde",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pretty_assertions"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "proc-macro2"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rust_decimal"
version = "1.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd"
dependencies = [
"arrayvec 0.7.4",
"num-traits",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "schemars"
version = "0.8.22"
dependencies = [
"arrayvec 0.5.2",
"arrayvec 0.7.4",
"bigdecimal 0.3.1",
"bigdecimal 0.4.2",
"bytes",
"chrono",
"dyn-clone",
"either",
"enumset",
"indexmap 1.9.3",
"indexmap 2.0.2",
"pretty_assertions",
"rust_decimal",
"schemars_derive",
"semver",
"serde",
"serde_json",
"smallvec",
"smol_str",
"trybuild",
"url",
"uuid 0.8.2",
"uuid 1.5.0",
]
[[package]]
name = "schemars_derive"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn",
]
[[package]]
name = "semver"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_derive_internals"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "smol_str"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9"
dependencies = [
"serde",
]
[[package]]
name = "syn"
version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
dependencies = [
"winapi-util",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "trybuild"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "196a58260a906cedb9bf6d8034b6379d0c11f552416960452f267402ceeddff1"
dependencies = [
"basic-toml",
"glob",
"once_cell",
"serde",
"serde_derive",
"serde_json",
"termcolor",
]
[[package]]
name = "unicode-bidi"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "url"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "uuid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"

419
vendor/schemars/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,419 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.60"
name = "schemars"
version = "0.8.22"
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
build = "build.rs"
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Generate JSON Schemas from Rust code"
homepage = "https://graham.cool/schemars/"
readme = "README.md"
keywords = [
"rust",
"json-schema",
"serde",
]
categories = ["encoding"]
license = "MIT"
repository = "https://github.com/GREsau/schemars"
[package.metadata.docs.rs]
all-features = true
[lib]
name = "schemars"
path = "src/lib.rs"
[[example]]
name = "custom_serialization"
path = "examples/custom_serialization.rs"
[[example]]
name = "custom_settings"
path = "examples/custom_settings.rs"
[[example]]
name = "doc_comments"
path = "examples/doc_comments.rs"
[[example]]
name = "enum_repr"
path = "examples/enum_repr.rs"
[[example]]
name = "from_value"
path = "examples/from_value.rs"
[[example]]
name = "main"
path = "examples/main.rs"
[[example]]
name = "remote_derive"
path = "examples/remote_derive.rs"
[[example]]
name = "schemars_attrs"
path = "examples/schemars_attrs.rs"
[[example]]
name = "serde_attrs"
path = "examples/serde_attrs.rs"
[[example]]
name = "validate"
path = "examples/validate.rs"
[[test]]
name = "arrayvec"
path = "tests/arrayvec.rs"
required-features = [
"arrayvec05",
"arrayvec07",
]
[[test]]
name = "bound"
path = "tests/bound.rs"
[[test]]
name = "bytes"
path = "tests/bytes.rs"
required-features = ["bytes"]
[[test]]
name = "chrono"
path = "tests/chrono.rs"
required-features = ["chrono"]
[[test]]
name = "crate_alias"
path = "tests/crate_alias.rs"
[[test]]
name = "decimal"
path = "tests/decimal.rs"
required-features = [
"rust_decimal",
"bigdecimal03",
"bigdecimal04",
]
[[test]]
name = "default"
path = "tests/default.rs"
[[test]]
name = "deprecated"
path = "tests/deprecated.rs"
[[test]]
name = "dereference"
path = "tests/dereference.rs"
[[test]]
name = "docs"
path = "tests/docs.rs"
[[test]]
name = "either"
path = "tests/either.rs"
required-features = ["either"]
[[test]]
name = "enum"
path = "tests/enum.rs"
[[test]]
name = "enum_deny_unknown_fields"
path = "tests/enum_deny_unknown_fields.rs"
[[test]]
name = "enum_repr"
path = "tests/enum_repr.rs"
[[test]]
name = "enumset"
path = "tests/enumset.rs"
required-features = ["enumset"]
[[test]]
name = "examples"
path = "tests/examples.rs"
[[test]]
name = "ffi"
path = "tests/ffi.rs"
[[test]]
name = "flatten"
path = "tests/flatten.rs"
[[test]]
name = "from_value"
path = "tests/from_value.rs"
[[test]]
name = "indexmap"
path = "tests/indexmap.rs"
required-features = ["indexmap"]
[[test]]
name = "indexmap2"
path = "tests/indexmap2.rs"
required-features = ["indexmap2"]
[[test]]
name = "inline_subschemas"
path = "tests/inline_subschemas.rs"
[[test]]
name = "macro"
path = "tests/macro.rs"
[[test]]
name = "nonzero_ints"
path = "tests/nonzero_ints.rs"
[[test]]
name = "property_name"
path = "tests/property_name.rs"
[[test]]
name = "range"
path = "tests/range.rs"
[[test]]
name = "remote_derive"
path = "tests/remote_derive.rs"
[[test]]
name = "remote_derive_generic"
path = "tests/remote_derive_generic.rs"
[[test]]
name = "result"
path = "tests/result.rs"
[[test]]
name = "same_name"
path = "tests/same_name.rs"
[[test]]
name = "schema_for_schema"
path = "tests/schema_for_schema.rs"
required-features = ["impl_json_schema"]
[[test]]
name = "schema_name"
path = "tests/schema_name.rs"
[[test]]
name = "schema_settings"
path = "tests/schema_settings.rs"
[[test]]
name = "schema_with_enum"
path = "tests/schema_with_enum.rs"
[[test]]
name = "schema_with_struct"
path = "tests/schema_with_struct.rs"
[[test]]
name = "semver"
path = "tests/semver.rs"
required-features = ["semver"]
[[test]]
name = "skip"
path = "tests/skip.rs"
[[test]]
name = "smallvec"
path = "tests/smallvec.rs"
required-features = ["smallvec"]
[[test]]
name = "smol_str"
path = "tests/smol_str.rs"
required-features = ["smol_str"]
[[test]]
name = "struct"
path = "tests/struct.rs"
[[test]]
name = "struct_additional_properties"
path = "tests/struct_additional_properties.rs"
[[test]]
name = "time"
path = "tests/time.rs"
[[test]]
name = "transparent"
path = "tests/transparent.rs"
[[test]]
name = "ui"
path = "tests/ui.rs"
required-features = ["ui_test"]
[[test]]
name = "url"
path = "tests/url.rs"
required-features = ["url"]
[[test]]
name = "uuid"
path = "tests/uuid.rs"
required-features = [
"uuid08",
"uuid1",
]
[[test]]
name = "validate"
path = "tests/validate.rs"
[[test]]
name = "validate_inner"
path = "tests/validate_inner.rs"
[dependencies.arrayvec05]
version = "0.5"
optional = true
default-features = false
package = "arrayvec"
[dependencies.arrayvec07]
version = "0.7"
optional = true
default-features = false
package = "arrayvec"
[dependencies.bigdecimal03]
version = "0.3"
optional = true
default-features = false
package = "bigdecimal"
[dependencies.bigdecimal04]
version = "0.4"
optional = true
default-features = false
package = "bigdecimal"
[dependencies.bytes]
version = "1.0"
optional = true
[dependencies.chrono]
version = "0.4"
optional = true
default-features = false
[dependencies.dyn-clone]
version = "1.0"
[dependencies.either]
version = "1.3"
optional = true
default-features = false
[dependencies.enumset]
version = "1.0"
optional = true
[dependencies.indexmap]
version = "1.2"
features = ["serde-1"]
optional = true
[dependencies.indexmap2]
version = "2.0"
features = ["serde"]
optional = true
package = "indexmap"
[dependencies.rust_decimal]
version = "1"
optional = true
default-features = false
[dependencies.schemars_derive]
version = "=0.8.22"
optional = true
[dependencies.semver]
version = "1.0.9"
features = ["serde"]
optional = true
[dependencies.serde]
version = "1.0"
features = ["derive"]
[dependencies.serde_json]
version = "1.0.25"
[dependencies.smallvec]
version = "1.0"
optional = true
[dependencies.smol_str]
version = "0.1.17"
optional = true
[dependencies.url]
version = "2.0"
optional = true
default-features = false
[dependencies.uuid08]
version = "0.8"
optional = true
default-features = false
package = "uuid"
[dependencies.uuid1]
version = "1.0"
optional = true
default-features = false
package = "uuid"
[dev-dependencies.pretty_assertions]
version = "1.2.1"
[dev-dependencies.trybuild]
version = "1.0"
[features]
arrayvec = ["arrayvec05"]
bigdecimal = ["bigdecimal03"]
default = ["derive"]
derive = ["schemars_derive"]
derive_json_schema = ["impl_json_schema"]
impl_json_schema = ["derive"]
indexmap1 = ["indexmap"]
preserve_order = ["indexmap"]
raw_value = ["serde_json/raw_value"]
ui_test = []
uuid = ["uuid08"]

21
vendor/schemars/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Graham Esau
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

286
vendor/schemars/README.md vendored Normal file
View File

@@ -0,0 +1,286 @@
# Schemars
> [!NOTE]
> Schemars 1.0 is in development on [the v1 branch](https://github.com/GREsau/schemars/tree/v1), see [draft PR 290](https://github.com/GREsau/schemars/pull/290) for updates
[![CI Build](https://img.shields.io/github/actions/workflow/status/GREsau/schemars/ci.yml?branch=master&logo=GitHub)](https://github.com/GREsau/schemars/actions)
[![Crates.io](https://img.shields.io/crates/v/schemars)](https://crates.io/crates/schemars)
[![Docs](https://docs.rs/schemars/badge.svg)](https://docs.rs/schemars)
[![MSRV 1.60+](https://img.shields.io/badge/schemars-rustc_1.60+-lightgray.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html)
Generate JSON Schema documents from Rust code
## Basic Usage
If you don't really care about the specifics, the easiest way to generate a JSON schema for your types is to `#[derive(JsonSchema)]` and use the `schema_for!` macro. All fields of the type must also implement `JsonSchema` - Schemars implements this for many standard library types.
```rust
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
```
<details>
<summary>Click to see the output JSON schema...</summary>
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": ["my_bool", "my_int"],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
},
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "object",
"required": ["StringNewType"],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": ["StructVariant"],
"properties": {
"StructVariant": {
"type": "object",
"required": ["floats"],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}
```
</details>
### Serde Compatibility
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema _should_ match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
```rust
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct MyStruct {
#[serde(rename = "myNumber")]
pub my_int: i32,
pub my_bool: bool,
#[serde(default)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(untagged)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
```
<details>
<summary>Click to see the output JSON schema...</summary>
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": ["myBool", "myNumber"],
"properties": {
"myBool": {
"type": "boolean"
},
"myNullableEnum": {
"default": null,
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer",
"format": "int32"
}
},
"additionalProperties": false,
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": ["floats"],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
]
}
}
}
```
</details>
`#[serde(...)]` attributes can be overriden using `#[schemars(...)]` attributes, which behave identically (e.g. `#[schemars(rename_all = "camelCase")]`). You may find this useful if you want to change the generated schema without affecting Serde's behaviour, or if you're just not using Serde.
### Schema from Example Value
If you want a schema for a type that can't/doesn't implement `JsonSchema`, but does implement `serde::Serialize`, then you can generate a JSON schema from a value of that type. However, this schema will generally be less precise than if the type implemented `JsonSchema` - particularly when it involves enums, since schemars will not make any assumptions about the structure of an enum based on a single variant.
```rust
use schemars::schema_for_value;
use serde::Serialize;
#[derive(Serialize)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Serialize)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
let schema = schema_for_value!(MyStruct {
my_int: 123,
my_bool: true,
my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string()))
});
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
```
<details>
<summary>Click to see the output JSON schema...</summary>
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"examples": [
{
"my_bool": true,
"my_int": 123,
"my_nullable_enum": {
"StringNewType": "foo"
}
}
],
"type": "object",
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer"
},
"my_nullable_enum": true
}
}
```
</details>
## Feature Flags
- `derive` (enabled by default) - provides `#[derive(JsonSchema)]` macro
- `impl_json_schema` - implements `JsonSchema` for Schemars types themselves
- `preserve_order` - keep the order of struct fields in `Schema` and `SchemaObject`
- `raw_value` - implements `JsonSchema` for `serde_json::value::RawValue` (enables the serde_json `raw_value` feature)
Schemars can implement `JsonSchema` on types from several popular crates, enabled via feature flags (dependency versions are shown in brackets):
- `chrono` - [chrono](https://crates.io/crates/chrono) (^0.4)
- `indexmap1` - [indexmap](https://crates.io/crates/indexmap) (^1.2)
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
- `either` - [either](https://crates.io/crates/either) (^1.3)
- `uuid08` - [uuid](https://crates.io/crates/uuid) (^0.8)
- `uuid1` - [uuid](https://crates.io/crates/uuid) (^1.0)
- `smallvec` - [smallvec](https://crates.io/crates/smallvec) (^1.0)
- `arrayvec05` - [arrayvec](https://crates.io/crates/arrayvec) (^0.5)
- `arrayvec07` - [arrayvec](https://crates.io/crates/arrayvec) (^0.7)
- `url` - [url](https://crates.io/crates/url) (^2.0)
- `bytes` - [bytes](https://crates.io/crates/bytes) (^1.0)
- `enumset` - [enumset](https://crates.io/crates/enumset) (^1.0)
- `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
- `bigdecimal03` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3)
- `bigdecimal04` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.4)
- `smol_str` - [smol_str](https://crates.io/crates/smol_str) (^0.1.17)
- `semver` - [semver](https://crates.io/crates/semver) (^1.0.9)
For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so:
```toml
[dependencies]
schemars = { version = "0.8", features = ["chrono"] }
```

25
vendor/schemars/build.rs vendored Normal file
View File

@@ -0,0 +1,25 @@
use std::env;
// Based on https://github.com/serde-rs/serde/blob/master/serde/build.rs
fn main() {
let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// Whitelist of archs that support std::sync::atomic module. Ideally we
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
// Instead this is based on rustc's src/librustc_target/spec/*.rs.
let has_atomic64 = target.starts_with("x86_64")
|| target.starts_with("i686")
|| target.starts_with("aarch64")
|| target.starts_with("powerpc64")
|| target.starts_with("sparc64")
|| target.starts_with("mips64el");
let has_atomic32 = has_atomic64 || emscripten;
if has_atomic64 {
println!("cargo:rustc-cfg=std_atomic64");
}
if has_atomic32 {
println!("cargo:rustc-cfg=std_atomic");
}
}

View File

@@ -0,0 +1,60 @@
use schemars::schema::{Schema, SchemaObject};
use schemars::{r#gen::SchemaGenerator, schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
// `int_as_string` and `bool_as_string` use the schema for `String`.
#[derive(Default, Deserialize, Serialize, JsonSchema)]
pub struct MyStruct {
#[serde(default = "eight", with = "as_string")]
#[schemars(with = "String")]
pub int_as_string: i32,
#[serde(default = "eight")]
pub int_normal: i32,
#[serde(default, with = "as_string")]
#[schemars(schema_with = "make_custom_schema")]
pub bool_as_string: bool,
#[serde(default)]
pub bool_normal: bool,
}
fn make_custom_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema: SchemaObject = <String>::json_schema(generator).into();
schema.format = Some("boolean".to_owned());
schema.into()
}
fn eight() -> i32 {
8
}
// This module serializes values as strings
mod as_string {
use serde::{de::Error, Deserialize, Deserializer, Serializer};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: std::fmt::Display,
S: Serializer,
{
serializer.collect_str(value)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: std::str::FromStr,
D: Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
string
.parse()
.map_err(|_| D::Error::custom("Input was not valid"))
}
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"properties": {
"bool_as_string": {
"default": "false",
"type": "string",
"format": "boolean"
},
"bool_normal": {
"default": false,
"type": "boolean"
},
"int_as_string": {
"default": "8",
"type": "string"
},
"int_normal": {
"default": 8,
"type": "integer",
"format": "int32"
}
}
}

View File

@@ -0,0 +1,24 @@
use schemars::{r#gen::SchemaSettings, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let settings = SchemaSettings::draft07().with(|s| {
s.option_nullable = true;
s.option_add_null_type = false;
});
let generator = settings.into_generator();
let schema = generator.into_root_schema_for::<MyStruct>();
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,68 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"allOf": [
{
"$ref": "#/definitions/MyEnum"
}
],
"nullable": true
}
},
"definitions": {
"MyEnum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

View File

@@ -0,0 +1,33 @@
use schemars::{schema_for, JsonSchema};
/// # My Amazing Struct
/// This struct shows off generating a schema with
/// a custom title and description.
#[derive(JsonSchema)]
pub struct MyStruct {
/// # My Amazing Integer
pub my_int: i32,
/// This bool has a description, but no title.
pub my_bool: bool,
/// # A Nullable Enum
/// This enum might be set, or it might not.
pub my_nullable_enum: Option<MyEnum>,
}
/// # My Amazing Enum
#[derive(JsonSchema)]
pub enum MyEnum {
/// A wrapper around a `String`
StringNewType(String),
/// A struct-like enum variant which contains
/// some floats
StructVariant {
/// The floats themselves
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,79 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "My Amazing Struct",
"description": "This struct shows off generating a schema with a custom title and description.",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"description": "This bool has a description, but no title.",
"type": "boolean"
},
"my_int": {
"title": "My Amazing Integer",
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"title": "A Nullable Enum",
"description": "This enum might be set, or it might not.",
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
},
"definitions": {
"MyEnum": {
"title": "My Amazing Enum",
"oneOf": [
{
"description": "A wrapper around a `String`",
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"description": "A struct-like enum variant which contains some floats",
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"description": "The floats themselves",
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

15
vendor/schemars/examples/enum_repr.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
use schemars::{schema_for, JsonSchema_repr};
#[derive(JsonSchema_repr)]
#[repr(u8)]
enum SmallPrime {
Two = 2,
Three = 3,
Five = 5,
Seven = 7,
}
fn main() {
let schema = schema_for!(SmallPrime);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,11 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "SmallPrime",
"type": "integer",
"enum": [
2,
3,
5,
7
]
}

24
vendor/schemars/examples/from_value.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
use schemars::schema_for_value;
use serde::Serialize;
#[derive(Serialize)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Serialize)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for_value!(MyStruct {
my_int: 123,
my_bool: true,
my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string()))
});
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,23 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"examples": [
{
"my_bool": true,
"my_int": 123,
"my_nullable_enum": {
"StringNewType": "foo"
}
}
],
"type": "object",
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer"
},
"my_nullable_enum": true
}
}

19
vendor/schemars/examples/main.rs vendored Normal file
View File

@@ -0,0 +1,19 @@
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,70 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
},
"definitions": {
"MyEnum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

View File

@@ -0,0 +1,42 @@
// Pretend that this is somebody else's crate, not a module.
mod other_crate {
// Neither Schemars nor the other crate provides a JsonSchema impl
// for this struct.
pub struct Duration {
pub secs: i64,
pub nanos: i32,
}
}
////////////////////////////////////////////////////////////////////////////////
use other_crate::Duration;
use schemars::{schema_for, JsonSchema};
// This is just a copy of the remote data structure that Schemars can use to
// create a suitable JsonSchema impl.
#[derive(JsonSchema)]
#[serde(remote = "Duration")]
pub struct DurationDef {
pub secs: i64,
pub nanos: i32,
}
// Now the remote type can be used almost like it had its own JsonSchema impl
// all along. The `with` attribute gives the path to the definition for the
// remote type. Note that the real type of the field is the remote type, not
// the definition type.
#[derive(JsonSchema)]
pub struct Process {
pub command_line: String,
#[serde(with = "DurationDef")]
pub wall_time: Duration,
// Generic types must be explicitly specified with turbofix `::<>` syntax.
#[serde(with = "Vec::<DurationDef>")]
pub durations: Vec<Duration>,
}
fn main() {
let schema = schema_for!(Process);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,43 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Process",
"type": "object",
"required": [
"command_line",
"durations",
"wall_time"
],
"properties": {
"command_line": {
"type": "string"
},
"durations": {
"type": "array",
"items": {
"$ref": "#/definitions/Duration"
}
},
"wall_time": {
"$ref": "#/definitions/Duration"
}
},
"definitions": {
"Duration": {
"type": "object",
"required": [
"nanos",
"secs"
],
"properties": {
"nanos": {
"type": "integer",
"format": "int32"
},
"secs": {
"type": "integer",
"format": "int64"
}
}
}
}
}

View File

@@ -0,0 +1,30 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
pub struct MyStruct {
#[serde(rename = "thisIsOverridden")]
#[schemars(rename = "myNumber", range(min = 1, max = 10))]
pub my_int: i32,
pub my_bool: bool,
#[schemars(default)]
pub my_nullable_enum: Option<MyEnum>,
#[schemars(inner(regex(pattern = "^x$")))]
pub my_vec_str: Vec<String>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[schemars(untagged)]
pub enum MyEnum {
StringNewType(#[schemars(phone)] String),
StructVariant {
#[schemars(length(min = 1, max = 100))]
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,67 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"myBool",
"myNumber",
"myVecStr"
],
"properties": {
"myBool": {
"type": "boolean"
},
"myNullableEnum": {
"default": null,
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer",
"format": "int32",
"maximum": 10.0,
"minimum": 1.0
},
"myVecStr": {
"type": "array",
"items": {
"type": "string",
"pattern": "^x$"
}
}
},
"additionalProperties": false,
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "string",
"format": "phone"
},
{
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
},
"maxItems": 100,
"minItems": 1
}
}
}
]
}
}
}

24
vendor/schemars/examples/serde_attrs.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct MyStruct {
#[serde(rename = "myNumber")]
pub my_int: i32,
pub my_bool: bool,
#[serde(default)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(untagged)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,54 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"myBool",
"myNumber"
],
"properties": {
"myBool": {
"type": "boolean"
},
"myNullableEnum": {
"default": null,
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer",
"format": "int32"
}
},
"additionalProperties": false,
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
]
}
}
}

24
vendor/schemars/examples/validate.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
#[validate(range(min = 1, max = 10))]
pub my_int: i32,
pub my_bool: bool,
#[validate(required)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(#[validate(phone)] String),
StructVariant {
#[validate(length(min = 1, max = 100))]
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View File

@@ -0,0 +1,64 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int",
"my_nullable_enum"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32",
"maximum": 10.0,
"minimum": 1.0
},
"my_nullable_enum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string",
"format": "phone"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
},
"maxItems": 100,
"minItems": 1
}
}
}
},
"additionalProperties": false
}
]
}
}
}

171
vendor/schemars/src/_private.rs vendored Normal file
View File

@@ -0,0 +1,171 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::{InstanceType, ObjectValidation, Schema, SchemaObject};
use crate::{JsonSchema, Map, Set};
use serde::Serialize;
use serde_json::Value;
// Helper for generating schemas for flattened `Option` fields.
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
generator: &mut SchemaGenerator,
required: bool,
) -> Schema {
let mut schema = T::_schemars_private_non_optional_json_schema(generator);
if T::_schemars_private_is_option() && !required {
if let Schema::Object(SchemaObject {
object: Some(ref mut object_validation),
..
}) = schema
{
object_validation.required.clear();
}
}
schema
}
/// Hack to simulate specialization:
/// `MaybeSerializeWrapper(x).maybe_to_value()` will resolve to either
/// - The inherent method `MaybeSerializeWrapper::maybe_to_value(...)` if x is `Serialize`
/// - The trait method `NoSerialize::maybe_to_value(...)` from the blanket impl otherwise
#[doc(hidden)]
#[macro_export]
macro_rules! _schemars_maybe_to_value {
($expression:expr) => {{
#[allow(unused_imports)]
use $crate::_private::{MaybeSerializeWrapper, NoSerialize as _};
MaybeSerializeWrapper($expression).maybe_to_value()
}};
}
pub struct MaybeSerializeWrapper<T>(pub T);
pub trait NoSerialize: Sized {
fn maybe_to_value(self) -> Option<Value> {
None
}
}
impl<T> NoSerialize for T {}
impl<T: Serialize> MaybeSerializeWrapper<T> {
pub fn maybe_to_value(self) -> Option<Value> {
serde_json::value::to_value(self.0).ok()
}
}
/// Create a schema for a unit enum
pub fn new_unit_enum(variant: &str) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(vec![variant.into()]),
..SchemaObject::default()
})
}
/// Create a schema for an externally tagged enum
pub fn new_externally_tagged_enum(variant: &str, sub_schema: Schema) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
properties: {
let mut props = Map::new();
props.insert(variant.to_owned(), sub_schema);
props
},
required: {
let mut required = Set::new();
required.insert(variant.to_owned());
required
},
// Externally tagged variants must prohibit additional
// properties irrespective of the disposition of
// `deny_unknown_fields`. If additional properties were allowed
// one could easily construct an object that validated against
// multiple variants since here it's the properties rather than
// the values of a property that distingish between variants.
additional_properties: Some(Box::new(false.into())),
..Default::default()
})),
..SchemaObject::default()
})
}
/// Create a schema for an internally tagged enum
pub fn new_internally_tagged_enum(
tag_name: &str,
variant: &str,
deny_unknown_fields: bool,
) -> Schema {
let tag_schema = Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(vec![variant.into()]),
..Default::default()
});
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
properties: {
let mut props = Map::new();
props.insert(tag_name.to_owned(), tag_schema);
props
},
required: {
let mut required = Set::new();
required.insert(tag_name.to_owned());
required
},
additional_properties: deny_unknown_fields.then(|| Box::new(false.into())),
..Default::default()
})),
..SchemaObject::default()
})
}
pub fn insert_object_property<T: ?Sized + JsonSchema>(
obj: &mut ObjectValidation,
key: &str,
has_default: bool,
required: bool,
schema: Schema,
) {
obj.properties.insert(key.to_owned(), schema);
if !has_default && (required || !T::_schemars_private_is_option()) {
obj.required.insert(key.to_owned());
}
}
pub mod metadata {
use crate::Schema;
use serde_json::Value;
macro_rules! add_metadata_fn {
($method:ident, $name:ident, $ty:ty) => {
pub fn $method(schema: Schema, $name: impl Into<$ty>) -> Schema {
let value = $name.into();
if value == <$ty>::default() {
schema
} else {
let mut schema_obj = schema.into_object();
schema_obj.metadata().$name = value.into();
Schema::Object(schema_obj)
}
}
};
}
add_metadata_fn!(add_description, description, String);
add_metadata_fn!(add_id, id, String);
add_metadata_fn!(add_title, title, String);
add_metadata_fn!(add_deprecated, deprecated, bool);
add_metadata_fn!(add_read_only, read_only, bool);
add_metadata_fn!(add_write_only, write_only, bool);
add_metadata_fn!(add_default, default, Option<Value>);
pub fn add_examples<I: IntoIterator<Item = Value>>(schema: Schema, examples: I) -> Schema {
let mut schema_obj = schema.into_object();
schema_obj.metadata().examples.extend(examples);
Schema::Object(schema_obj)
}
}

180
vendor/schemars/src/flatten.rs vendored Normal file
View File

@@ -0,0 +1,180 @@
use crate::schema::*;
use crate::{Map, Set};
impl Schema {
/// This function is only public for use by schemars_derive.
///
/// It should not be considered part of the public API.
#[doc(hidden)]
pub fn flatten(self, other: Self) -> Schema {
if is_null_type(&self) {
return other;
} else if is_null_type(&other) {
return self;
}
let s1: SchemaObject = self.into();
let s2: SchemaObject = other.into();
Schema::Object(s1.merge(s2))
}
}
pub(crate) trait Merge: Sized {
fn merge(self, other: Self) -> Self;
}
macro_rules! impl_merge {
($ty:ident { merge: $($merge_field:ident)*, or: $($or_field:ident)*, }) => {
impl Merge for $ty {
fn merge(self, other: Self) -> Self {
$ty {
$($merge_field: self.$merge_field.merge(other.$merge_field),)*
$($or_field: self.$or_field.or(other.$or_field),)*
}
}
}
};
($ty:ident { or: $($or_field:ident)*, }) => {
impl_merge!( $ty { merge: , or: $($or_field)*, });
};
}
// For ObjectValidation::additional_properties.
impl Merge for Option<Box<Schema>> {
fn merge(self, other: Self) -> Self {
match (self.map(|x| *x), other.map(|x| *x)) {
// Perfer permissive schemas.
(Some(Schema::Bool(true)), _) => Some(Box::new(true.into())),
(_, Some(Schema::Bool(true))) => Some(Box::new(true.into())),
(None, _) => None,
(_, None) => None,
// Merge if we have two non-trivial schemas.
(Some(Schema::Object(s1)), Some(Schema::Object(s2))) => {
Some(Box::new(Schema::Object(s1.merge(s2))))
}
// Perfer the more permissive schema.
(Some(s1 @ Schema::Object(_)), Some(Schema::Bool(false))) => Some(Box::new(s1)),
(Some(Schema::Bool(false)), Some(s2 @ Schema::Object(_))) => Some(Box::new(s2)),
// Default to the null schema.
(Some(Schema::Bool(false)), Some(Schema::Bool(false))) => Some(Box::new(false.into())),
}
}
}
impl_merge!(SchemaObject {
merge: extensions instance_type enum_values
metadata subschemas number string array object,
or: format const_value reference,
});
impl Merge for Metadata {
fn merge(self, other: Self) -> Self {
Metadata {
id: self.id.or(other.id),
title: self.title.or(other.title),
description: self.description.or(other.description),
default: self.default.or(other.default),
deprecated: self.deprecated || other.deprecated,
read_only: self.read_only || other.read_only,
write_only: self.write_only || other.write_only,
examples: self.examples.merge(other.examples),
}
}
}
impl_merge!(SubschemaValidation {
or: all_of any_of one_of not if_schema then_schema else_schema,
});
impl_merge!(NumberValidation {
or: multiple_of maximum exclusive_maximum minimum exclusive_minimum,
});
impl_merge!(StringValidation {
or: max_length min_length pattern,
});
impl_merge!(ArrayValidation {
or: items additional_items max_items min_items unique_items contains,
});
impl_merge!(ObjectValidation {
merge: required properties pattern_properties additional_properties,
or: max_properties min_properties property_names,
});
impl<T: Merge> Merge for Option<T> {
fn merge(self, other: Self) -> Self {
match (self, other) {
(Some(x), Some(y)) => Some(x.merge(y)),
(None, y) => y,
(x, None) => x,
}
}
}
impl<T: Merge> Merge for Box<T> {
fn merge(mut self, other: Self) -> Self {
*self = (*self).merge(*other);
self
}
}
impl<T> Merge for Vec<T> {
fn merge(mut self, other: Self) -> Self {
self.extend(other);
self
}
}
impl<K, V> Merge for Map<K, V>
where
K: std::hash::Hash + Eq + Ord,
{
fn merge(mut self, other: Self) -> Self {
self.extend(other);
self
}
}
impl<T: Ord> Merge for Set<T> {
fn merge(mut self, other: Self) -> Self {
self.extend(other);
self
}
}
impl Merge for SingleOrVec<InstanceType> {
fn merge(self, other: Self) -> Self {
if self == other {
return self;
}
let mut vec = match (self, other) {
(SingleOrVec::Vec(v1), SingleOrVec::Vec(v2)) => v1.merge(v2),
(SingleOrVec::Vec(mut v), SingleOrVec::Single(s))
| (SingleOrVec::Single(s), SingleOrVec::Vec(mut v)) => {
v.push(*s);
v
}
(SingleOrVec::Single(s1), SingleOrVec::Single(s2)) => vec![*s1, *s2],
};
vec.sort();
vec.dedup();
SingleOrVec::Vec(vec)
}
}
fn is_null_type(schema: &Schema) -> bool {
let s = match schema {
Schema::Object(s) => s,
_ => return false,
};
let instance_type = match &s.instance_type {
Some(SingleOrVec::Single(t)) => t,
_ => return false,
};
**instance_type == InstanceType::Null
}

518
vendor/schemars/src/gen.rs vendored Normal file
View File

@@ -0,0 +1,518 @@
/*!
JSON Schema generator and settings.
This module is useful if you want more control over how the schema generated than the [`schema_for!`] macro gives you.
There are two main types in this module:
* [`SchemaSettings`], which defines what JSON Schema features should be used when generating schemas (for example, how `Option`s should be represented).
* [`SchemaGenerator`], which manages the generation of a schema document.
*/
use crate::schema::*;
use crate::{visit::*, JsonSchema, Map};
use dyn_clone::DynClone;
use serde::Serialize;
use std::borrow::Cow;
use std::collections::HashMap;
use std::{any::Any, collections::HashSet, fmt::Debug};
/// Settings to customize how Schemas are generated.
///
/// The default settings currently conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
/// If you require your generated schemas to conform to draft 7, consider using the [`draft07`](#method.draft07) method.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct SchemaSettings {
/// If `true`, schemas for [`Option<T>`](Option) will include a `nullable` property.
///
/// This is not part of the JSON Schema spec, but is used in Swagger/OpenAPI schemas.
///
/// Defaults to `false`.
pub option_nullable: bool,
/// If `true`, schemas for [`Option<T>`](Option) will have `null` added to their [`type`](../schema/struct.SchemaObject.html#structfield.instance_type).
///
/// Defaults to `true`.
pub option_add_null_type: bool,
/// A JSON pointer to the expected location of referenceable subschemas within the resulting root schema.
///
/// Defaults to `"#/definitions/"`.
pub definitions_path: String,
/// The URI of the meta-schema describing the structure of the generated schemas.
///
/// Defaults to `"http://json-schema.org/draft-07/schema#"`.
pub meta_schema: Option<String>,
/// A list of visitors that get applied to all generated root schemas.
pub visitors: Vec<Box<dyn GenVisitor>>,
/// Inline all subschemas instead of using references.
///
/// Some references may still be generated in schemas for recursive types.
///
/// Defaults to `false`.
pub inline_subschemas: bool,
}
impl Default for SchemaSettings {
fn default() -> SchemaSettings {
SchemaSettings::draft07()
}
}
impl SchemaSettings {
/// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7).
pub fn draft07() -> SchemaSettings {
SchemaSettings {
option_nullable: false,
option_add_null_type: true,
definitions_path: "#/definitions/".to_owned(),
meta_schema: Some("http://json-schema.org/draft-07/schema#".to_owned()),
visitors: vec![Box::new(RemoveRefSiblings)],
inline_subschemas: false,
}
}
/// Creates `SchemaSettings` that conform to [JSON Schema 2019-09](https://json-schema.org/specification-links.html#2019-09-formerly-known-as-draft-8).
pub fn draft2019_09() -> SchemaSettings {
SchemaSettings {
option_nullable: false,
option_add_null_type: true,
definitions_path: "#/definitions/".to_owned(),
meta_schema: Some("https://json-schema.org/draft/2019-09/schema".to_owned()),
visitors: Vec::default(),
inline_subschemas: false,
}
}
/// Creates `SchemaSettings` that conform to [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject).
pub fn openapi3() -> SchemaSettings {
SchemaSettings {
option_nullable: true,
option_add_null_type: false,
definitions_path: "#/components/schemas/".to_owned(),
meta_schema: Some(
"https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema"
.to_owned(),
),
visitors: vec![
Box::new(RemoveRefSiblings),
Box::new(ReplaceBoolSchemas {
skip_additional_properties: true,
}),
Box::new(SetSingleExample {
retain_examples: false,
}),
],
inline_subschemas: false,
}
}
/// Modifies the `SchemaSettings` by calling the given function.
///
/// # Example
/// ```
/// use schemars::r#gen::{SchemaGenerator, SchemaSettings};
///
/// let settings = SchemaSettings::default().with(|s| {
/// s.option_nullable = true;
/// s.option_add_null_type = false;
/// });
/// let generator = settings.into_generator();
/// ```
pub fn with(mut self, configure_fn: impl FnOnce(&mut Self)) -> Self {
configure_fn(&mut self);
self
}
/// Appends the given visitor to the list of [visitors](SchemaSettings::visitors) for these `SchemaSettings`.
pub fn with_visitor(mut self, visitor: impl Visitor + Debug + Clone + 'static) -> Self {
self.visitors.push(Box::new(visitor));
self
}
/// Creates a new [`SchemaGenerator`] using these settings.
pub fn into_generator(self) -> SchemaGenerator {
SchemaGenerator::new(self)
}
}
/// The main type used to generate JSON Schemas.
///
/// # Example
/// ```
/// use schemars::{JsonSchema, r#gen::SchemaGenerator};
///
/// #[derive(JsonSchema)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let generator = SchemaGenerator::default();
/// let schema = generator.into_root_schema_for::<MyStruct>();
/// ```
#[derive(Debug, Default)]
pub struct SchemaGenerator {
settings: SchemaSettings,
definitions: Map<String, Schema>,
pending_schema_ids: HashSet<Cow<'static, str>>,
schema_id_to_name: HashMap<Cow<'static, str>, String>,
used_schema_names: HashSet<String>,
}
impl Clone for SchemaGenerator {
fn clone(&self) -> Self {
Self {
settings: self.settings.clone(),
definitions: self.definitions.clone(),
pending_schema_ids: HashSet::new(),
schema_id_to_name: HashMap::new(),
used_schema_names: HashSet::new(),
}
}
}
impl From<SchemaSettings> for SchemaGenerator {
fn from(settings: SchemaSettings) -> Self {
settings.into_generator()
}
}
impl SchemaGenerator {
/// Creates a new `SchemaGenerator` using the given settings.
pub fn new(settings: SchemaSettings) -> SchemaGenerator {
SchemaGenerator {
settings,
..Default::default()
}
}
/// Borrows the [`SchemaSettings`] being used by this `SchemaGenerator`.
///
/// # Example
/// ```
/// use schemars::r#gen::SchemaGenerator;
///
/// let generator = SchemaGenerator::default();
/// let settings = generator.settings();
///
/// assert_eq!(settings.option_add_null_type, true);
/// ```
pub fn settings(&self) -> &SchemaSettings {
&self.settings
}
#[deprecated = "This method no longer has any effect."]
pub fn make_extensible(&self, _schema: &mut SchemaObject) {}
#[deprecated = "Use `Schema::Bool(true)` instead"]
pub fn schema_for_any(&self) -> Schema {
Schema::Bool(true)
}
#[deprecated = "Use `Schema::Bool(false)` instead"]
pub fn schema_for_none(&self) -> Schema {
Schema::Bool(false)
}
/// Generates a JSON Schema for the type `T`, and returns either the schema itself or a `$ref` schema referencing `T`'s schema.
///
/// If `T` is [referenceable](JsonSchema::is_referenceable), this will add `T`'s schema to this generator's definitions, and
/// return a `$ref` schema referencing that schema. Otherwise, this method behaves identically to [`JsonSchema::json_schema`].
///
/// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// add them to the `SchemaGenerator`'s schema definitions.
pub fn subschema_for<T: ?Sized + JsonSchema>(&mut self) -> Schema {
let id = T::schema_id();
let return_ref = T::is_referenceable()
&& (!self.settings.inline_subschemas || self.pending_schema_ids.contains(&id));
if return_ref {
let name = match self.schema_id_to_name.get(&id).cloned() {
Some(n) => n,
None => {
let base_name = T::schema_name();
let mut name = String::new();
if self.used_schema_names.contains(&base_name) {
for i in 2.. {
name = format!("{}{}", base_name, i);
if !self.used_schema_names.contains(&name) {
break;
}
}
} else {
name = base_name;
}
self.used_schema_names.insert(name.clone());
self.schema_id_to_name.insert(id.clone(), name.clone());
name
}
};
let reference = format!("{}{}", self.settings.definitions_path, name);
if !self.definitions.contains_key(&name) {
self.insert_new_subschema_for::<T>(name, id);
}
Schema::new_ref(reference)
} else {
self.json_schema_internal::<T>(id)
}
}
fn insert_new_subschema_for<T: ?Sized + JsonSchema>(
&mut self,
name: String,
id: Cow<'static, str>,
) {
let dummy = Schema::Bool(false);
// insert into definitions BEFORE calling json_schema to avoid infinite recursion
self.definitions.insert(name.clone(), dummy);
let schema = self.json_schema_internal::<T>(id);
self.definitions.insert(name, schema);
}
/// Borrows the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated.
///
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
/// themselves.
pub fn definitions(&self) -> &Map<String, Schema> {
&self.definitions
}
/// Mutably borrows the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated.
///
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
/// themselves.
pub fn definitions_mut(&mut self) -> &mut Map<String, Schema> {
&mut self.definitions
}
/// Returns the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated,
/// leaving an empty map in its place.
///
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
/// themselves.
pub fn take_definitions(&mut self) -> Map<String, Schema> {
std::mem::take(&mut self.definitions)
}
/// Returns an iterator over the [visitors](SchemaSettings::visitors) being used by this `SchemaGenerator`.
pub fn visitors_mut(&mut self) -> impl Iterator<Item = &mut dyn GenVisitor> {
self.settings.visitors.iter_mut().map(|v| v.as_mut())
}
/// Generates a root JSON Schema for the type `T`.
///
/// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// add them to the `SchemaGenerator`'s schema definitions and include them in the returned `SchemaObject`'s
/// [`definitions`](../schema/struct.Metadata.html#structfield.definitions)
pub fn root_schema_for<T: ?Sized + JsonSchema>(&mut self) -> RootSchema {
let mut schema = self.json_schema_internal::<T>(T::schema_id()).into_object();
schema.metadata().title.get_or_insert_with(T::schema_name);
let mut root = RootSchema {
meta_schema: self.settings.meta_schema.clone(),
definitions: self.definitions.clone(),
schema,
};
for visitor in &mut self.settings.visitors {
visitor.visit_root_schema(&mut root)
}
root
}
/// Consumes `self` and generates a root JSON Schema for the type `T`.
///
/// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// include them in the returned `SchemaObject`'s [`definitions`](../schema/struct.Metadata.html#structfield.definitions)
pub fn into_root_schema_for<T: ?Sized + JsonSchema>(mut self) -> RootSchema {
let mut schema = self.json_schema_internal::<T>(T::schema_id()).into_object();
schema.metadata().title.get_or_insert_with(T::schema_name);
let mut root = RootSchema {
meta_schema: self.settings.meta_schema,
definitions: self.definitions,
schema,
};
for visitor in &mut self.settings.visitors {
visitor.visit_root_schema(&mut root)
}
root
}
/// Generates a root JSON Schema for the given example value.
///
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`root_schema_for()`](Self::root_schema_for())
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
pub fn root_schema_for_value<T: ?Sized + Serialize>(
&mut self,
value: &T,
) -> Result<RootSchema, serde_json::Error> {
let mut schema = value
.serialize(crate::ser::Serializer {
generator: self,
include_title: true,
})?
.into_object();
if let Ok(example) = serde_json::to_value(value) {
schema.metadata().examples.push(example);
}
let mut root = RootSchema {
meta_schema: self.settings.meta_schema.clone(),
definitions: self.definitions.clone(),
schema,
};
for visitor in &mut self.settings.visitors {
visitor.visit_root_schema(&mut root)
}
Ok(root)
}
/// Consumes `self` and generates a root JSON Schema for the given example value.
///
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`into_root_schema_for()!`](Self::into_root_schema_for())
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
pub fn into_root_schema_for_value<T: ?Sized + Serialize>(
mut self,
value: &T,
) -> Result<RootSchema, serde_json::Error> {
let mut schema = value
.serialize(crate::ser::Serializer {
generator: &mut self,
include_title: true,
})?
.into_object();
if let Ok(example) = serde_json::to_value(value) {
schema.metadata().examples.push(example);
}
let mut root = RootSchema {
meta_schema: self.settings.meta_schema,
definitions: self.definitions,
schema,
};
for visitor in &mut self.settings.visitors {
visitor.visit_root_schema(&mut root)
}
Ok(root)
}
/// Attemps to find the schema that the given `schema` is referencing.
///
/// If the given `schema` has a [`$ref`](../schema/struct.SchemaObject.html#structfield.reference) property which refers
/// to another schema in `self`'s schema definitions, the referenced schema will be returned. Otherwise, returns `None`.
///
/// # Example
/// ```
/// use schemars::{JsonSchema, r#gen::SchemaGenerator};
///
/// #[derive(JsonSchema)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let mut generator = SchemaGenerator::default();
/// let ref_schema = generator.subschema_for::<MyStruct>();
///
/// assert!(ref_schema.is_ref());
///
/// let dereferenced = generator.dereference(&ref_schema);
///
/// assert!(dereferenced.is_some());
/// assert!(!dereferenced.unwrap().is_ref());
/// assert_eq!(dereferenced, generator.definitions().get("MyStruct"));
/// ```
pub fn dereference<'a>(&'a self, schema: &Schema) -> Option<&'a Schema> {
match schema {
Schema::Object(SchemaObject {
reference: Some(ref schema_ref),
..
}) => {
let definitions_path = &self.settings().definitions_path;
if schema_ref.starts_with(definitions_path) {
let name = &schema_ref[definitions_path.len()..];
self.definitions.get(name)
} else {
None
}
}
_ => None,
}
}
fn json_schema_internal<T: ?Sized + JsonSchema>(&mut self, id: Cow<'static, str>) -> Schema {
struct PendingSchemaState<'a> {
generator: &'a mut SchemaGenerator,
id: Cow<'static, str>,
did_add: bool,
}
impl<'a> PendingSchemaState<'a> {
fn new(generator: &'a mut SchemaGenerator, id: Cow<'static, str>) -> Self {
let did_add = generator.pending_schema_ids.insert(id.clone());
Self {
generator,
id,
did_add,
}
}
}
impl Drop for PendingSchemaState<'_> {
fn drop(&mut self) {
if self.did_add {
self.generator.pending_schema_ids.remove(&self.id);
}
}
}
let pss = PendingSchemaState::new(self, id);
T::json_schema(pss.generator)
}
}
/// A [Visitor](Visitor) which implements additional traits required to be included in a [SchemaSettings].
///
/// You will rarely need to use this trait directly as it is automatically implemented for any type which implements all of:
/// - [`Visitor`]
/// - [`std::fmt::Debug`]
/// - [`std::any::Any`] (implemented for all `'static` types)
/// - [`std::clone::Clone`]
///
/// # Example
/// ```
/// use schemars::visit::Visitor;
/// use schemars::r#gen::GenVisitor;
///
/// #[derive(Debug, Clone)]
/// struct MyVisitor;
///
/// impl Visitor for MyVisitor { }
///
/// let v: &dyn GenVisitor = &MyVisitor;
/// assert!(v.as_any().is::<MyVisitor>());
/// ```
pub trait GenVisitor: Visitor + Debug + DynClone + Any {
/// Upcasts this visitor into an `Any`, which can be used to inspect and manipulate it as its concrete type.
fn as_any(&self) -> &dyn Any;
}
dyn_clone::clone_trait_object!(GenVisitor);
impl<T> GenVisitor for T
where
T: Visitor + Debug + Clone + Any,
{
fn as_any(&self) -> &dyn Any {
self
}
}

View File

@@ -0,0 +1,106 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
// Does not require T: JsonSchema.
impl<T> JsonSchema for [T; 0] {
no_ref_schema!();
fn schema_name() -> String {
"EmptyArray".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("[]")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
max_items: Some(0),
..Default::default()
})),
..Default::default()
}
.into()
}
}
macro_rules! array_impls {
($($len:tt)+) => {
$(
impl<T: JsonSchema> JsonSchema for [T; $len] {
no_ref_schema!();
fn schema_name() -> String {
format!("Array_size_{}_of_{}", $len, T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("[{}; {}]", $len, T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(generator.subschema_for::<T>().into()),
max_items: Some($len),
min_items: Some($len),
..Default::default()
})),
..Default::default()
}
.into()
}
}
)+
}
}
array_impls! {
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::{schema_for, schema_object_for};
use pretty_assertions::assert_eq;
#[test]
fn schema_for_array() {
let schema = schema_object_for::<[i32; 8]>();
assert_eq!(
schema.instance_type,
Some(SingleOrVec::from(InstanceType::Array))
);
let array_validation = schema.array.unwrap();
assert_eq!(
array_validation.items,
Some(SingleOrVec::from(schema_for::<i32>()))
);
assert_eq!(array_validation.max_items, Some(8));
assert_eq!(array_validation.min_items, Some(8));
}
// SomeStruct does not implement JsonSchema
struct SomeStruct;
#[test]
fn schema_for_empty_array() {
let schema = schema_object_for::<[SomeStruct; 0]>();
assert_eq!(
schema.instance_type,
Some(SingleOrVec::from(InstanceType::Array))
);
let array_validation = schema.array.unwrap();
assert_eq!(array_validation.max_items, Some(0));
}
}

View File

@@ -0,0 +1,37 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use arrayvec05::{Array, ArrayString, ArrayVec};
use std::convert::TryInto;
// Do not set maxLength on the schema as that describes length in characters, but we only
// know max length in bytes.
forward_impl!((<A> JsonSchema for ArrayString<A> where A: Array<Item = u8> + Copy) => String);
impl<A: Array> JsonSchema for ArrayVec<A>
where
A::Item: JsonSchema,
{
no_ref_schema!();
fn schema_name() -> String {
format!(
"Array_up_to_size_{}_of_{}",
A::CAPACITY,
A::Item::schema_name()
)
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(generator.subschema_for::<A::Item>().into()),
max_items: A::CAPACITY.try_into().ok(),
..Default::default()
})),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,33 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use arrayvec07::{ArrayString, ArrayVec};
use std::convert::TryInto;
// Do not set maxLength on the schema as that describes length in characters, but we only
// know max length in bytes.
forward_impl!((<const CAP: usize> JsonSchema for ArrayString<CAP>) => String);
impl<T, const CAP: usize> JsonSchema for ArrayVec<T, CAP>
where
T: JsonSchema,
{
no_ref_schema!();
fn schema_name() -> String {
format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name())
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(generator.subschema_for::<T>().into()),
max_items: CAP.try_into().ok(),
..Default::default()
})),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,47 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::sync::atomic::*;
forward_impl!(AtomicBool => bool);
forward_impl!(AtomicI8 => i8);
forward_impl!(AtomicI16 => i16);
forward_impl!(AtomicI32 => i32);
#[cfg(std_atomic64)]
forward_impl!(AtomicI64 => i64);
forward_impl!(AtomicIsize => isize);
forward_impl!(AtomicU8 => u8);
forward_impl!(AtomicU16 => u16);
forward_impl!(AtomicU32 => u32);
#[cfg(std_atomic64)]
forward_impl!(AtomicU64 => u64);
forward_impl!(AtomicUsize => usize);
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::schema_object_for;
use pretty_assertions::assert_eq;
#[test]
fn schema_for_atomics() {
let atomic_schema = schema_object_for::<(
AtomicBool,
AtomicI8,
AtomicI16,
AtomicI32,
AtomicI64,
AtomicIsize,
AtomicU8,
AtomicU16,
AtomicU32,
AtomicU64,
AtomicUsize,
)>();
let basic_schema =
schema_object_for::<(bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize)>();
assert_eq!(atomic_schema, basic_schema);
}
}

View File

@@ -0,0 +1,7 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use bytes::{Bytes, BytesMut};
forward_impl!((JsonSchema for Bytes) => Vec<u8>);
forward_impl!((JsonSchema for BytesMut) => Vec<u8>);

View File

@@ -0,0 +1,68 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use chrono::prelude::*;
use serde_json::json;
use std::borrow::Cow;
impl JsonSchema for Weekday {
no_ref_schema!();
fn schema_name() -> String {
"Weekday".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("chrono::Weekday")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(vec![
json!("Mon"),
json!("Tue"),
json!("Wed"),
json!("Thu"),
json!("Fri"),
json!("Sat"),
json!("Sun"),
]),
..Default::default()
}
.into()
}
}
macro_rules! formatted_string_impl {
($ty:ident, $format:literal) => {
formatted_string_impl!($ty, $format, JsonSchema for $ty);
};
($ty:ident, $format:literal, $($desc:tt)+) => {
impl $($desc)+ {
no_ref_schema!();
fn schema_name() -> String {
stringify!($ty).to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(chrono::$ty))
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some($format.to_owned()),
..Default::default()
}
.into()
}
}
};
}
formatted_string_impl!(NaiveDate, "date");
formatted_string_impl!(NaiveDateTime, "partial-date-time");
formatted_string_impl!(NaiveTime, "partial-date-time");
formatted_string_impl!(DateTime, "date-time", <Tz: TimeZone> JsonSchema for DateTime<Tz>);

View File

@@ -0,0 +1,230 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use serde_json::json;
use std::borrow::Cow;
use std::ops::{Bound, Range, RangeInclusive};
impl<T: JsonSchema> JsonSchema for Option<T> {
no_ref_schema!();
fn schema_name() -> String {
format!("Nullable_{}", T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Option<{}>", T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema = generator.subschema_for::<T>();
if generator.settings().option_add_null_type {
schema = match schema {
Schema::Bool(true) => Schema::Bool(true),
Schema::Bool(false) => <()>::json_schema(generator),
Schema::Object(SchemaObject {
instance_type: Some(ref mut instance_type),
..
}) => {
add_null_type(instance_type);
schema
}
schema => SchemaObject {
// TODO technically the schema already accepts null, so this may be unnecessary
subschemas: Some(Box::new(SubschemaValidation {
any_of: Some(vec![schema, <()>::json_schema(generator)]),
..Default::default()
})),
..Default::default()
}
.into(),
}
}
if generator.settings().option_nullable {
let mut schema_obj = schema.into_object();
schema_obj
.extensions
.insert("nullable".to_owned(), json!(true));
schema = Schema::Object(schema_obj);
};
schema
}
fn _schemars_private_non_optional_json_schema(generator: &mut SchemaGenerator) -> Schema {
T::_schemars_private_non_optional_json_schema(generator)
}
fn _schemars_private_is_option() -> bool {
true
}
}
fn add_null_type(instance_type: &mut SingleOrVec<InstanceType>) {
match instance_type {
SingleOrVec::Single(ty) if **ty != InstanceType::Null => {
*instance_type = vec![**ty, InstanceType::Null].into()
}
SingleOrVec::Vec(ty) if !ty.contains(&InstanceType::Null) => ty.push(InstanceType::Null),
_ => {}
};
}
impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
fn schema_name() -> String {
format!("Result_of_{}_or_{}", T::schema_name(), E::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Result<{}, {}>", T::schema_id(), E::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut ok_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = ok_schema.object();
obj.required.insert("Ok".to_owned());
obj.properties
.insert("Ok".to_owned(), generator.subschema_for::<T>());
let mut err_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = err_schema.object();
obj.required.insert("Err".to_owned());
obj.properties
.insert("Err".to_owned(), generator.subschema_for::<E>());
let mut schema = SchemaObject::default();
schema.subschemas().one_of = Some(vec![ok_schema.into(), err_schema.into()]);
schema.into()
}
}
impl<T: JsonSchema> JsonSchema for Bound<T> {
fn schema_name() -> String {
format!("Bound_of_{}", T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Bound<{}>", T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut included_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = included_schema.object();
obj.required.insert("Included".to_owned());
obj.properties
.insert("Included".to_owned(), generator.subschema_for::<T>());
let mut excluded_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = excluded_schema.object();
obj.required.insert("Excluded".to_owned());
obj.properties
.insert("Excluded".to_owned(), generator.subschema_for::<T>());
let unbounded_schema = SchemaObject {
instance_type: Some(InstanceType::String.into()),
const_value: Some(json!("Unbounded")),
..Default::default()
};
let mut schema = SchemaObject::default();
schema.subschemas().one_of = Some(vec![
included_schema.into(),
excluded_schema.into(),
unbounded_schema.into(),
]);
schema.into()
}
}
impl<T: JsonSchema> JsonSchema for Range<T> {
fn schema_name() -> String {
format!("Range_of_{}", T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Range<{}>", T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = schema.object();
obj.required.insert("start".to_owned());
obj.required.insert("end".to_owned());
obj.properties
.insert("start".to_owned(), generator.subschema_for::<T>());
obj.properties
.insert("end".to_owned(), generator.subschema_for::<T>());
schema.into()
}
}
forward_impl!((<T: JsonSchema> JsonSchema for RangeInclusive<T>) => Range<T>);
forward_impl!((<T: ?Sized> JsonSchema for std::marker::PhantomData<T>) => ());
forward_impl!((<'a> JsonSchema for std::fmt::Arguments<'a>) => String);
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::{schema_for, schema_object_for};
use pretty_assertions::assert_eq;
#[test]
fn schema_for_option() {
let schema = schema_object_for::<Option<i32>>();
assert_eq!(
schema.instance_type,
Some(vec![InstanceType::Integer, InstanceType::Null].into())
);
assert_eq!(schema.extensions.get("nullable"), None);
assert_eq!(schema.subschemas.is_none(), true);
}
#[test]
fn schema_for_option_with_ref() {
use crate as schemars;
#[derive(JsonSchema)]
struct Foo;
let schema = schema_object_for::<Option<Foo>>();
assert_eq!(schema.instance_type, None);
assert_eq!(schema.extensions.get("nullable"), None);
assert_eq!(schema.subschemas.is_some(), true);
let any_of = schema.subschemas.unwrap().any_of.unwrap();
assert_eq!(any_of.len(), 2);
assert_eq!(any_of[0], Schema::new_ref("#/definitions/Foo".to_string()));
assert_eq!(any_of[1], schema_for::<()>());
}
#[test]
fn schema_for_result() {
let schema = schema_object_for::<Result<bool, String>>();
let one_of = schema.subschemas.unwrap().one_of.unwrap();
assert_eq!(one_of.len(), 2);
let ok_schema: SchemaObject = one_of[0].clone().into();
let obj = ok_schema.object.unwrap();
assert!(obj.required.contains("Ok"));
assert_eq!(obj.properties["Ok"], schema_for::<bool>());
let err_schema: SchemaObject = one_of[1].clone().into();
let obj = err_schema.object.unwrap();
assert!(obj.required.contains("Err"));
assert_eq!(obj.properties["Err"], schema_for::<String>());
}
}

View File

@@ -0,0 +1,39 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
macro_rules! decimal_impl {
($type:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
fn schema_name() -> String {
"Decimal".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("Decimal")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
string: Some(Box::new(StringValidation {
pattern: Some(r"^-?[0-9]+(\.[0-9]+)?$".to_owned()),
..Default::default()
})),
..Default::default()
}
.into()
}
}
};
}
#[cfg(feature = "rust_decimal")]
decimal_impl!(rust_decimal::Decimal);
#[cfg(feature = "bigdecimal03")]
decimal_impl!(bigdecimal03::BigDecimal);
#[cfg(feature = "bigdecimal04")]
decimal_impl!(bigdecimal04::BigDecimal);

View File

@@ -0,0 +1,30 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use either::Either;
use std::borrow::Cow;
impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
no_ref_schema!();
fn schema_name() -> String {
format!("Either_{}_or_{}", L::schema_name(), R::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!(
"either::Either<{}, {}>",
L::schema_id(),
R::schema_id()
))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema = SchemaObject::default();
schema.subschemas().any_of = Some(vec![
generator.subschema_for::<L>(),
generator.subschema_for::<R>(),
]);
schema.into()
}
}

View File

@@ -0,0 +1,6 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use enumset::{EnumSet, EnumSetType};
forward_impl!((<T> JsonSchema for EnumSet<T> where T: EnumSetType + JsonSchema) => std::collections::BTreeSet<T>);

View File

@@ -0,0 +1,44 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};
impl JsonSchema for OsString {
fn schema_name() -> String {
"OsString".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("std::ffi::OsString")
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut unix_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = unix_schema.object();
obj.required.insert("Unix".to_owned());
obj.properties
.insert("Unix".to_owned(), <Vec<u8>>::json_schema(generator));
let mut win_schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = win_schema.object();
obj.required.insert("Windows".to_owned());
obj.properties
.insert("Windows".to_owned(), <Vec<u16>>::json_schema(generator));
let mut schema = SchemaObject::default();
schema.subschemas().one_of = Some(vec![unix_schema.into(), win_schema.into()]);
schema.into()
}
}
forward_impl!(OsStr => OsString);
forward_impl!(CString => Vec<u8>);
forward_impl!(CStr => Vec<u8>);

View File

@@ -0,0 +1,8 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use indexmap::{IndexMap, IndexSet};
use std::collections::{HashMap, HashSet};
forward_impl!((<K, V: JsonSchema, H> JsonSchema for IndexMap<K, V, H>) => HashMap<K, V, H>);
forward_impl!((<T: JsonSchema, H> JsonSchema for IndexSet<T, H>) => HashSet<T, H>);

View File

@@ -0,0 +1,8 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use indexmap2::{IndexMap, IndexSet};
use std::collections::{HashMap, HashSet};
forward_impl!((<K, V: JsonSchema, H> JsonSchema for IndexMap<K, V, H>) => HashMap<K, V, H>);
forward_impl!((<T: JsonSchema, H> JsonSchema for IndexSet<T, H>) => HashSet<T, H>);

View File

@@ -0,0 +1,39 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
macro_rules! map_impl {
($($desc:tt)+) => {
impl $($desc)+
where
V: JsonSchema,
{
no_ref_schema!();
fn schema_name() -> String {
format!("Map_of_{}", V::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Map<{}>", V::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let subschema = generator.subschema_for::<V>();
SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
additional_properties: Some(Box::new(subschema)),
..Default::default()
})),
..Default::default()
}
.into()
}
}
};
}
map_impl!(<K, V> JsonSchema for std::collections::BTreeMap<K, V>);
map_impl!(<K, V, H> JsonSchema for std::collections::HashMap<K, V, H>);

View File

@@ -0,0 +1,89 @@
macro_rules! no_ref_schema {
() => {
fn is_referenceable() -> bool {
false
}
};
}
macro_rules! forward_impl {
(($($impl:tt)+) => $target:ty) => {
impl $($impl)+ {
fn is_referenceable() -> bool {
<$target>::is_referenceable()
}
fn schema_name() -> String {
<$target>::schema_name()
}
fn schema_id() -> std::borrow::Cow<'static, str> {
<$target>::schema_id()
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
<$target>::json_schema(generator)
}
fn _schemars_private_non_optional_json_schema(generator: &mut SchemaGenerator) -> Schema {
<$target>::_schemars_private_non_optional_json_schema(generator)
}
fn _schemars_private_is_option() -> bool {
<$target>::_schemars_private_is_option()
}
}
};
($ty:ty => $target:ty) => {
forward_impl!((JsonSchema for $ty) => $target);
};
}
mod array;
#[cfg(feature = "arrayvec05")]
mod arrayvec05;
#[cfg(feature = "arrayvec07")]
mod arrayvec07;
#[cfg(std_atomic)]
mod atomic;
#[cfg(feature = "bytes")]
mod bytes;
#[cfg(feature = "chrono")]
mod chrono;
mod core;
#[cfg(any(
feature = "rust_decimal",
feature = "bigdecimal03",
feature = "bigdecimal04"
))]
mod decimal;
#[cfg(feature = "either")]
mod either;
#[cfg(feature = "enumset")]
mod enumset;
mod ffi;
#[cfg(feature = "indexmap")]
mod indexmap;
#[cfg(feature = "indexmap2")]
mod indexmap2;
mod maps;
mod nonzero_signed;
mod nonzero_unsigned;
mod primitives;
#[cfg(feature = "semver")]
mod semver;
mod sequences;
mod serdejson;
#[cfg(feature = "smallvec")]
mod smallvec;
#[cfg(feature = "smol_str")]
mod smol_str;
mod time;
mod tuple;
#[cfg(feature = "url")]
mod url;
#[cfg(feature = "uuid08")]
mod uuid08;
#[cfg(feature = "uuid1")]
mod uuid1;
mod wrapper;

View File

@@ -0,0 +1,39 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use std::num::*;
macro_rules! nonzero_unsigned_impl {
($type:ty => $primitive:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
fn schema_name() -> String {
stringify!($type).to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(std::num::$type))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let zero_schema: Schema = SchemaObject {
const_value: Some(0.into()),
..Default::default()
}
.into();
let mut schema: SchemaObject = <$primitive>::json_schema(generator).into();
schema.subschemas().not = Some(Box::from(zero_schema));
schema.into()
}
}
};
}
nonzero_unsigned_impl!(NonZeroI8 => i8);
nonzero_unsigned_impl!(NonZeroI16 => i16);
nonzero_unsigned_impl!(NonZeroI32 => i32);
nonzero_unsigned_impl!(NonZeroI64 => i64);
nonzero_unsigned_impl!(NonZeroI128 => i128);
nonzero_unsigned_impl!(NonZeroIsize => isize);

View File

@@ -0,0 +1,49 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use std::num::*;
macro_rules! nonzero_unsigned_impl {
($type:ty => $primitive:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
fn schema_name() -> String {
stringify!($type).to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(std::num::$type))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema: SchemaObject = <$primitive>::json_schema(generator).into();
schema.number().minimum = Some(1.0);
schema.into()
}
}
};
}
nonzero_unsigned_impl!(NonZeroU8 => u8);
nonzero_unsigned_impl!(NonZeroU16 => u16);
nonzero_unsigned_impl!(NonZeroU32 => u32);
nonzero_unsigned_impl!(NonZeroU64 => u64);
nonzero_unsigned_impl!(NonZeroU128 => u128);
nonzero_unsigned_impl!(NonZeroUsize => usize);
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::schema_object_for;
use pretty_assertions::assert_eq;
#[test]
fn schema_for_nonzero_u32() {
let schema = schema_object_for::<NonZeroU32>();
assert_eq!(schema.number.unwrap().minimum, Some(1.0));
assert_eq!(schema.instance_type, Some(InstanceType::Integer.into()));
assert_eq!(schema.format, Some("uint32".to_owned()));
}
}

View File

@@ -0,0 +1,119 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::path::{Path, PathBuf};
macro_rules! simple_impl {
($type:ty => $instance_type:ident) => {
simple_impl!($type => $instance_type, stringify!($instance_type), None);
};
($type:ty => $instance_type:ident, $format:literal) => {
simple_impl!($type => $instance_type, $format, Some($format.to_owned()));
};
($type:ty => $instance_type:ident, $name:expr, $format:expr) => {
impl JsonSchema for $type {
no_ref_schema!();
fn schema_name() -> String {
$name.to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed($name)
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::$instance_type.into()),
format: $format,
..Default::default()
}
.into()
}
}
};
}
simple_impl!(str => String);
simple_impl!(String => String);
simple_impl!(bool => Boolean);
simple_impl!(f32 => Number, "float");
simple_impl!(f64 => Number, "double");
simple_impl!(i8 => Integer, "int8");
simple_impl!(i16 => Integer, "int16");
simple_impl!(i32 => Integer, "int32");
simple_impl!(i64 => Integer, "int64");
simple_impl!(i128 => Integer, "int128");
simple_impl!(isize => Integer, "int");
simple_impl!(() => Null);
simple_impl!(Path => String);
simple_impl!(PathBuf => String);
simple_impl!(Ipv4Addr => String, "ipv4");
simple_impl!(Ipv6Addr => String, "ipv6");
simple_impl!(IpAddr => String, "ip");
simple_impl!(SocketAddr => String);
simple_impl!(SocketAddrV4 => String);
simple_impl!(SocketAddrV6 => String);
macro_rules! unsigned_impl {
($type:ty => $instance_type:ident, $format:expr) => {
impl JsonSchema for $type {
no_ref_schema!();
fn schema_name() -> String {
$format.to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed($format)
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
let mut schema = SchemaObject {
instance_type: Some(InstanceType::$instance_type.into()),
format: Some($format.to_owned()),
..Default::default()
};
schema.number().minimum = Some(0.0);
schema.into()
}
}
};
}
unsigned_impl!(u8 => Integer, "uint8");
unsigned_impl!(u16 => Integer, "uint16");
unsigned_impl!(u32 => Integer, "uint32");
unsigned_impl!(u64 => Integer, "uint64");
unsigned_impl!(u128 => Integer, "uint128");
unsigned_impl!(usize => Integer, "uint");
impl JsonSchema for char {
no_ref_schema!();
fn schema_name() -> String {
"Character".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("char")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
string: Some(Box::new(StringValidation {
min_length: Some(1),
max_length: Some(1),
..Default::default()
})),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,30 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use semver::Version;
use std::borrow::Cow;
impl JsonSchema for Version {
no_ref_schema!();
fn schema_name() -> String {
"Version".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("semver::Version")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
string: Some(Box::new(StringValidation {
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
pattern: Some(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$".to_owned()),
..Default::default()
})),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,78 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
macro_rules! seq_impl {
($($desc:tt)+) => {
impl $($desc)+
where
T: JsonSchema,
{
no_ref_schema!();
fn schema_name() -> String {
format!("Array_of_{}", T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("[{}]", T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(generator.subschema_for::<T>().into()),
..Default::default()
})),
..Default::default()
}
.into()
}
}
};
}
macro_rules! set_impl {
($($desc:tt)+) => {
impl $($desc)+
where
T: JsonSchema,
{
no_ref_schema!();
fn schema_name() -> String {
format!("Set_of_{}", T::schema_name())
}
fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("Set<{}>", T::schema_id()))
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
unique_items: Some(true),
items: Some(generator.subschema_for::<T>().into()),
..Default::default()
})),
..Default::default()
}
.into()
}
}
};
}
seq_impl!(<T> JsonSchema for std::collections::BinaryHeap<T>);
seq_impl!(<T> JsonSchema for std::collections::LinkedList<T>);
seq_impl!(<T> JsonSchema for [T]);
seq_impl!(<T> JsonSchema for Vec<T>);
seq_impl!(<T> JsonSchema for std::collections::VecDeque<T>);
set_impl!(<T> JsonSchema for std::collections::BTreeSet<T>);
set_impl!(<T, H> JsonSchema for std::collections::HashSet<T, H>);

View File

@@ -0,0 +1,47 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use serde_json::{Map, Number, Value};
use std::borrow::Cow;
use std::collections::BTreeMap;
impl JsonSchema for Value {
no_ref_schema!();
fn schema_name() -> String {
"AnyValue".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("AnyValue")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
Schema::Bool(true)
}
}
forward_impl!(Map<String, Value> => BTreeMap<String, Value>);
impl JsonSchema for Number {
no_ref_schema!();
fn schema_name() -> String {
"Number".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("Number")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::Number.into()),
..Default::default()
}
.into()
}
}
#[cfg(feature = "raw_value")]
forward_impl!(serde_json::value::RawValue => Value);

View File

@@ -0,0 +1,6 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use smallvec::{Array, SmallVec};
forward_impl!((<A: Array> JsonSchema for SmallVec<A> where A::Item: JsonSchema) => Vec<A::Item>);

View File

@@ -0,0 +1,6 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use smol_str::SmolStr;
forward_impl!(SmolStr => String);

View File

@@ -0,0 +1,57 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use std::time::{Duration, SystemTime};
impl JsonSchema for Duration {
fn schema_name() -> String {
"Duration".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("std::time::Duration")
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = schema.object();
obj.required.insert("secs".to_owned());
obj.required.insert("nanos".to_owned());
obj.properties
.insert("secs".to_owned(), <u64>::json_schema(generator));
obj.properties
.insert("nanos".to_owned(), <u32>::json_schema(generator));
schema.into()
}
}
impl JsonSchema for SystemTime {
fn schema_name() -> String {
"SystemTime".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("std::time::SystemTime")
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let mut schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
..Default::default()
};
let obj = schema.object();
obj.required.insert("secs_since_epoch".to_owned());
obj.required.insert("nanos_since_epoch".to_owned());
obj.properties
.insert("secs_since_epoch".to_owned(), <u64>::json_schema(generator));
obj.properties.insert(
"nanos_since_epoch".to_owned(),
<u32>::json_schema(generator),
);
schema.into()
}
}

View File

@@ -0,0 +1,90 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
macro_rules! tuple_impls {
($($len:expr => ($($name:ident)+))+) => {
$(
impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) {
no_ref_schema!();
fn schema_name() -> String {
let mut name = "Tuple_of_".to_owned();
name.push_str(&[$($name::schema_name()),+].join("_and_"));
name
}
fn schema_id() -> Cow<'static, str> {
let mut id = "(".to_owned();
id.push_str(&[$($name::schema_id()),+].join(","));
id.push(')');
Cow::Owned(id)
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
let items = vec![
$(generator.subschema_for::<$name>()),+
];
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(items.into()),
max_items: Some($len),
min_items: Some($len),
..Default::default()
})),
..Default::default()
}
.into()
}
}
)+
}
}
tuple_impls! {
1 => (T0)
2 => (T0 T1)
3 => (T0 T1 T2)
4 => (T0 T1 T2 T3)
5 => (T0 T1 T2 T3 T4)
6 => (T0 T1 T2 T3 T4 T5)
7 => (T0 T1 T2 T3 T4 T5 T6)
8 => (T0 T1 T2 T3 T4 T5 T6 T7)
9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8)
10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9)
11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::{schema_for, schema_object_for};
use pretty_assertions::assert_eq;
#[test]
fn schema_for_map_any_value() {
let schema = schema_object_for::<(i32, bool)>();
assert_eq!(
schema.instance_type,
Some(SingleOrVec::from(InstanceType::Array))
);
let array_validation = schema.array.unwrap();
assert_eq!(
array_validation.items,
Some(SingleOrVec::Vec(vec![
schema_for::<i32>(),
schema_for::<bool>()
]))
);
assert_eq!(array_validation.max_items, Some(2));
assert_eq!(array_validation.min_items, Some(2));
}
}

View File

@@ -0,0 +1,26 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use url::Url;
impl JsonSchema for Url {
no_ref_schema!();
fn schema_name() -> String {
"Url".to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("url::Url")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some("uri".to_owned()),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,26 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use uuid08::Uuid;
impl JsonSchema for Uuid {
no_ref_schema!();
fn schema_name() -> String {
"Uuid".to_string()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("uuid::Uuid")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some("uuid".to_string()),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,26 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::*;
use crate::JsonSchema;
use std::borrow::Cow;
use uuid1::Uuid;
impl JsonSchema for Uuid {
no_ref_schema!();
fn schema_name() -> String {
"Uuid".to_string()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("uuid::Uuid")
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some("uuid".to_string()),
..Default::default()
}
.into()
}
}

View File

@@ -0,0 +1,24 @@
use crate::r#gen::SchemaGenerator;
use crate::schema::Schema;
use crate::JsonSchema;
macro_rules! wrapper_impl {
($($desc:tt)+) => {
forward_impl!(($($desc)+ where T: JsonSchema) => T);
};
}
wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a T);
wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a mut T);
wrapper_impl!(<T: ?Sized> JsonSchema for Box<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::rc::Rc<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::rc::Weak<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Arc<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Weak<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Mutex<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::RwLock<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::cell::Cell<T>);
wrapper_impl!(<T: ?Sized> JsonSchema for std::cell::RefCell<T>);
wrapper_impl!(<'a, T: ?Sized + ToOwned> JsonSchema for std::borrow::Cow<'a, T>);
wrapper_impl!(<T> JsonSchema for std::num::Wrapping<T>);
wrapper_impl!(<T> JsonSchema for std::cmp::Reverse<T>);

200
vendor/schemars/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,200 @@
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
/// The map type used by schemars types.
///
/// Currently a `BTreeMap` or `IndexMap` can be used, but this may change to a different implementation
/// with a similar interface in a future version of schemars.
/// The `IndexMap` will be used when the `preserve_order` feature flag is set.
#[cfg(not(feature = "preserve_order"))]
pub type Map<K, V> = std::collections::BTreeMap<K, V>;
#[cfg(feature = "preserve_order")]
pub type Map<K, V> = indexmap::IndexMap<K, V>;
/// The set type used by schemars types.
///
/// Currently a `BTreeSet`, but this may change to a different implementation
/// with a similar interface in a future version of schemars.
pub type Set<T> = std::collections::BTreeSet<T>;
/// A view into a single entry in a map, which may either be vacant or occupied.
//
/// This is constructed from the `entry` method on `BTreeMap` or `IndexMap`,
/// depending on whether the `preserve_order` feature flag is set.
#[cfg(not(feature = "preserve_order"))]
pub type MapEntry<'a, K, V> = std::collections::btree_map::Entry<'a, K, V>;
#[cfg(feature = "preserve_order")]
pub type MapEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>;
mod flatten;
mod json_schema_impls;
mod ser;
#[macro_use]
mod macros;
/// This module is only public for use by `schemars_derive`. It should not need to be used by code
/// outside of `schemars`, and should not be considered part of the public API.
#[doc(hidden)]
pub mod _private;
pub mod r#gen;
pub mod schema;
pub mod visit;
pub use r#gen::SchemaGenerator;
#[cfg(feature = "schemars_derive")]
extern crate schemars_derive;
use std::borrow::Cow;
#[cfg(feature = "schemars_derive")]
pub use schemars_derive::*;
// Export serde_json so schemars_derive can use it
#[doc(hidden)]
pub use serde_json as _serde_json;
use schema::Schema;
/// A type which can be described as a JSON Schema document.
///
/// This is implemented for many Rust primitive and standard library types.
///
/// This can also be automatically derived on most custom types with `#[derive(JsonSchema)]`.
///
/// # Examples
/// Deriving an implementation:
/// ```
/// use schemars::{schema_for, JsonSchema};
///
/// #[derive(JsonSchema)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let my_schema = schema_for!(MyStruct);
/// ```
///
/// When manually implementing `JsonSchema`, as well as determining an appropriate schema,
/// you will need to determine an appropriate name and ID for the type.
/// For non-generic types, the type name/path are suitable for this:
/// ```
/// use schemars::{r#gen::SchemaGenerator, schema::Schema, JsonSchema};
/// use std::borrow::Cow;
///
/// struct NonGenericType;
///
/// impl JsonSchema for NonGenericType {
/// fn schema_name() -> String {
/// // Exclude the module path to make the name in generated schemas clearer.
/// "NonGenericType".to_owned()
/// }
///
/// fn schema_id() -> Cow<'static, str> {
/// // Include the module, in case a type with the same name is in another module/crate
/// Cow::Borrowed(concat!(module_path!(), "::NonGenericType"))
/// }
///
/// fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
/// todo!()
/// }
/// }
///
/// assert_eq!(NonGenericType::schema_id(), <&mut NonGenericType>::schema_id());
/// ```
///
/// But generic type parameters which may affect the generated schema should typically be included in the name/ID:
/// ```
/// use schemars::{r#gen::SchemaGenerator, schema::Schema, JsonSchema};
/// use std::{borrow::Cow, marker::PhantomData};
///
/// struct GenericType<T>(PhantomData<T>);
///
/// impl<T: JsonSchema> JsonSchema for GenericType<T> {
/// fn schema_name() -> String {
/// format!("GenericType_{}", T::schema_name())
/// }
///
/// fn schema_id() -> Cow<'static, str> {
/// Cow::Owned(format!(
/// "{}::GenericType<{}>",
/// module_path!(),
/// T::schema_id()
/// ))
/// }
///
/// fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
/// todo!()
/// }
/// }
///
/// assert_eq!(<GenericType<i32>>::schema_id(), <&mut GenericType<&i32>>::schema_id());
/// ```
///
pub trait JsonSchema {
/// Whether JSON Schemas generated for this type should be re-used where possible using the `$ref` keyword.
///
/// For trivial types (such as primitives), this should return `false`. For more complex types, it should return `true`.
/// For recursive types, this **must** return `true` to prevent infinite cycles when generating schemas.
///
/// By default, this returns `true`.
fn is_referenceable() -> bool {
true
}
/// The name of the generated JSON Schema.
///
/// This is used as the title for root schemas, and the key within the root's `definitions` property for subschemas.
fn schema_name() -> String;
/// Returns a string that uniquely identifies the schema produced by this type.
///
/// This does not have to be a human-readable string, and the value will not itself be included in generated schemas.
/// If two types produce different schemas, then they **must** have different `schema_id()`s,
/// but two types that produce identical schemas should *ideally* have the same `schema_id()`.
///
/// The default implementation returns the same value as `schema_name()`.
fn schema_id() -> Cow<'static, str> {
Cow::Owned(Self::schema_name())
}
/// Generates a JSON Schema for this type.
///
/// If the returned schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// add them to the [`SchemaGenerator`](r#gen::SchemaGenerator)'s schema definitions.
///
/// This should not return a `$ref` schema.
fn json_schema(generator: &mut r#gen::SchemaGenerator) -> Schema;
// TODO document and bring into public API?
#[doc(hidden)]
fn _schemars_private_non_optional_json_schema(generator: &mut r#gen::SchemaGenerator) -> Schema {
Self::json_schema(generator)
}
// TODO document and bring into public API?
#[doc(hidden)]
fn _schemars_private_is_option() -> bool {
false
}
}
#[cfg(test)]
pub mod tests {
use super::*;
pub fn schema_object_for<T: JsonSchema>() -> schema::SchemaObject {
schema_object(schema_for::<T>())
}
pub fn schema_for<T: JsonSchema>() -> schema::Schema {
let mut generator = r#gen::SchemaGenerator::default();
T::json_schema(&mut generator)
}
pub fn schema_object(schema: schema::Schema) -> schema::SchemaObject {
match schema {
schema::Schema::Object(o) => o,
s => panic!("Schema was not an object: {:?}", s),
}
}
}

78
vendor/schemars/src/macros.rs vendored Normal file
View File

@@ -0,0 +1,78 @@
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given type using default settings.
///
/// The type must implement [`JsonSchema`](crate::JsonSchema).
///
/// # Example
/// ```
/// use schemars::{schema_for, JsonSchema};
///
/// #[derive(JsonSchema)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let my_schema = schema_for!(MyStruct);
/// ```
#[cfg(doc)]
#[macro_export]
macro_rules! schema_for {
($type:ty) => {
$crate::r#gen::SchemaGenerator::default().into_root_schema_for::<$type>()
};
}
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given type using default settings.
///
/// The type must implement [`JsonSchema`](crate::JsonSchema).
///
/// # Example
/// ```
/// use schemars::{schema_for, JsonSchema};
///
/// #[derive(JsonSchema)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let my_schema = schema_for!(MyStruct);
/// ```
#[cfg(not(doc))]
#[macro_export]
macro_rules! schema_for {
($type:ty) => {
$crate::r#gen::SchemaGenerator::default().into_root_schema_for::<$type>()
};
($_:expr) => {
compile_error!("This argument to `schema_for!` is not a type - did you mean to use `schema_for_value!` instead?")
};
}
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given example value using default settings.
///
/// The value must implement [`Serialize`](serde::Serialize). If the value also implements [`JsonSchema`](crate::JsonSchema),
/// then prefer using the [`schema_for!`](schema_for) macro which will generally produce a more precise schema,
/// particularly when the value contains any enums.
///
/// If the `Serialize` implementation of the value decides to fail, this macro will panic.
/// For a non-panicking alternative, create a [`SchemaGenerator`](crate::r#gen::SchemaGenerator) and use
/// its [`into_root_schema_for_value`](crate::r#gen::SchemaGenerator::into_root_schema_for_value) method.
///
/// # Example
/// ```
/// use schemars::schema_for_value;
///
/// #[derive(serde::Serialize)]
/// struct MyStruct {
/// foo: i32,
/// }
///
/// let my_schema = schema_for_value!(MyStruct { foo: 123 });
/// ```
#[macro_export]
macro_rules! schema_for_value {
($value:expr) => {
$crate::r#gen::SchemaGenerator::default()
.into_root_schema_for_value(&$value)
.unwrap()
};
}

551
vendor/schemars/src/schema.rs vendored Normal file
View File

@@ -0,0 +1,551 @@
/*!
JSON Schema types.
*/
#[cfg(feature = "impl_json_schema")]
use crate as schemars;
#[cfg(feature = "impl_json_schema")]
use crate::JsonSchema;
use crate::{Map, Set};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::ops::Deref;
/// A JSON Schema.
#[allow(clippy::large_enum_variant)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(untagged)]
pub enum Schema {
/// A trivial boolean JSON Schema.
///
/// The schema `true` matches everything (always passes validation), whereas the schema `false`
/// matches nothing (always fails validation).
Bool(bool),
/// A JSON Schema object.
Object(SchemaObject),
}
impl Schema {
/// Creates a new `$ref` schema.
///
/// The given reference string should be a URI reference. This will usually be a JSON Pointer
/// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6).
pub fn new_ref(reference: String) -> Self {
SchemaObject::new_ref(reference).into()
}
/// Returns `true` if `self` is a `$ref` schema.
///
/// If `self` is a [`SchemaObject`] with `Some` [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`.
/// Otherwise, returns `false`.
pub fn is_ref(&self) -> bool {
match self {
Schema::Object(o) => o.is_ref(),
_ => false,
}
}
/// Converts the given schema (if it is a boolean schema) into an equivalent schema object.
///
/// If the given schema is already a schema object, this has no effect.
///
/// # Example
/// ```
/// use schemars::schema::{Schema, SchemaObject};
///
/// let bool_schema = Schema::Bool(true);
///
/// assert_eq!(bool_schema.into_object(), SchemaObject::default());
/// ```
pub fn into_object(self) -> SchemaObject {
match self {
Schema::Object(o) => o,
Schema::Bool(true) => SchemaObject::default(),
Schema::Bool(false) => SchemaObject {
subschemas: Some(Box::new(SubschemaValidation {
not: Some(Schema::Object(Default::default()).into()),
..Default::default()
})),
..Default::default()
},
}
}
}
impl From<SchemaObject> for Schema {
fn from(o: SchemaObject) -> Self {
Schema::Object(o)
}
}
impl From<bool> for Schema {
fn from(b: bool) -> Self {
Schema::Bool(b)
}
}
/// The root object of a JSON Schema document.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct RootSchema {
/// The `$schema` keyword.
///
/// See [JSON Schema 8.1.1. The "$schema" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.1.1).
#[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
pub meta_schema: Option<String>,
/// The root schema itself.
#[serde(flatten)]
pub schema: SchemaObject,
/// The `definitions` keyword.
///
/// In JSON Schema draft 2019-09 this was replaced by $defs, but in Schemars this is still
/// serialized as `definitions` for backward-compatibility.
///
/// See [JSON Schema 8.2.5. Schema Re-Use With "$defs"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.5),
/// and [JSON Schema (draft 07) 9. Schema Re-Use With "definitions"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9).
#[serde(alias = "$defs", skip_serializing_if = "Map::is_empty")]
pub definitions: Map<String, Schema>,
}
/// A JSON Schema object.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct SchemaObject {
/// Properties which annotate the [`SchemaObject`] which typically have no effect when an object is being validated against the schema.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub metadata: Option<Box<Metadata>>,
/// The `type` keyword.
///
/// See [JSON Schema Validation 6.1.1. "type"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1)
/// and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub instance_type: Option<SingleOrVec<InstanceType>>,
/// The `format` keyword.
///
/// See [JSON Schema Validation 7. A Vocabulary for Semantic Content With "format"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-7).
#[serde(skip_serializing_if = "Option::is_none")]
pub format: Option<String>,
/// The `enum` keyword.
///
/// See [JSON Schema Validation 6.1.2. "enum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.2)
#[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
pub enum_values: Option<Vec<Value>>,
/// The `const` keyword.
///
/// See [JSON Schema Validation 6.1.3. "const"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.3)
#[serde(
rename = "const",
skip_serializing_if = "Option::is_none",
deserialize_with = "allow_null"
)]
pub const_value: Option<Value>,
/// Properties of the [`SchemaObject`] which define validation assertions in terms of other schemas.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub subschemas: Option<Box<SubschemaValidation>>,
/// Properties of the [`SchemaObject`] which define validation assertions for numbers.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub number: Option<Box<NumberValidation>>,
/// Properties of the [`SchemaObject`] which define validation assertions for strings.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub string: Option<Box<StringValidation>>,
/// Properties of the [`SchemaObject`] which define validation assertions for arrays.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub array: Option<Box<ArrayValidation>>,
/// Properties of the [`SchemaObject`] which define validation assertions for objects.
#[serde(flatten, deserialize_with = "skip_if_default")]
pub object: Option<Box<ObjectValidation>>,
/// The `$ref` keyword.
///
/// See [JSON Schema 8.2.4.1. Direct References with "$ref"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.4.1).
#[serde(rename = "$ref", skip_serializing_if = "Option::is_none")]
pub reference: Option<String>,
/// Arbitrary extra properties which are not part of the JSON Schema specification, or which `schemars` does not support.
#[serde(flatten)]
pub extensions: Map<String, Value>,
}
// Deserializing "null" to `Option<Value>` directly results in `None`,
// this function instead makes it deserialize to `Some(Value::Null)`.
fn allow_null<'de, D>(de: D) -> Result<Option<Value>, D::Error>
where
D: serde::Deserializer<'de>,
{
Value::deserialize(de).map(Option::Some)
}
fn skip_if_default<'de, D, T>(deserializer: D) -> Result<Option<Box<T>>, D::Error>
where
D: serde::Deserializer<'de>,
T: Deserialize<'de> + Default + PartialEq,
{
let value = T::deserialize(deserializer)?;
if value == T::default() {
Ok(None)
} else {
Ok(Some(Box::new(value)))
}
}
macro_rules! get_or_insert_default_fn {
($name:ident, $ret:ty) => {
get_or_insert_default_fn!(
concat!(
"Returns a mutable reference to this schema's [`",
stringify!($ret),
"`](#structfield.",
stringify!($name),
"), creating it if it was `None`."
),
$name,
$ret
);
};
($doc:expr, $name:ident, $ret:ty) => {
#[doc = $doc]
pub fn $name(&mut self) -> &mut $ret {
self.$name.get_or_insert_with(Default::default)
}
};
}
impl SchemaObject {
/// Creates a new `$ref` schema.
///
/// The given reference string should be a URI reference. This will usually be a JSON Pointer
/// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6).
pub fn new_ref(reference: String) -> Self {
SchemaObject {
reference: Some(reference),
..Default::default()
}
}
/// Returns `true` if `self` is a `$ref` schema.
///
/// If `self` has `Some` [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`.
/// Otherwise, returns `false`.
pub fn is_ref(&self) -> bool {
self.reference.is_some()
}
/// Returns `true` if `self` accepts values of the given type, according to the [`instance_type`](struct.SchemaObject.html#structfield.instance_type) field.
///
/// This is a basic check that always returns `true` if no `instance_type` is specified on the schema,
/// and does not check any subschemas. Because of this, both `{}` and `{"not": {}}` accept any type according
/// to this method.
pub fn has_type(&self, ty: InstanceType) -> bool {
self.instance_type
.as_ref()
.map_or(true, |x| x.contains(&ty))
}
get_or_insert_default_fn!(metadata, Metadata);
get_or_insert_default_fn!(subschemas, SubschemaValidation);
get_or_insert_default_fn!(number, NumberValidation);
get_or_insert_default_fn!(string, StringValidation);
get_or_insert_default_fn!(array, ArrayValidation);
get_or_insert_default_fn!(object, ObjectValidation);
}
impl From<Schema> for SchemaObject {
fn from(schema: Schema) -> Self {
schema.into_object()
}
}
/// Properties which annotate a [`SchemaObject`] which typically have no effect when an object is being validated against the schema.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct Metadata {
/// The `$id` keyword.
///
/// See [JSON Schema 8.2.2. The "$id" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.2).
#[serde(rename = "$id", skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
/// The `title` keyword.
///
/// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
/// The `description` keyword.
///
/// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// The `default` keyword.
///
/// See [JSON Schema Validation 9.2. "default"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.2).
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "allow_null"
)]
pub default: Option<Value>,
/// The `deprecated` keyword.
///
/// See [JSON Schema Validation 9.3. "deprecated"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.3).
#[serde(skip_serializing_if = "is_false")]
pub deprecated: bool,
/// The `readOnly` keyword.
///
/// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4).
#[serde(skip_serializing_if = "is_false")]
pub read_only: bool,
/// The `writeOnly` keyword.
///
/// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4).
#[serde(skip_serializing_if = "is_false")]
pub write_only: bool,
/// The `examples` keyword.
///
/// See [JSON Schema Validation 9.5. "examples"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.5).
#[serde(skip_serializing_if = "Vec::is_empty")]
pub examples: Vec<Value>,
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_false(b: &bool) -> bool {
!b
}
/// Properties of a [`SchemaObject`] which define validation assertions in terms of other schemas.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct SubschemaValidation {
/// The `allOf` keyword.
///
/// See [JSON Schema 9.2.1.1. "allOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub all_of: Option<Vec<Schema>>,
/// The `anyOf` keyword.
///
/// See [JSON Schema 9.2.1.2. "anyOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub any_of: Option<Vec<Schema>>,
/// The `oneOf` keyword.
///
/// See [JSON Schema 9.2.1.3. "oneOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub one_of: Option<Vec<Schema>>,
/// The `not` keyword.
///
/// See [JSON Schema 9.2.1.4. "not"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).
#[serde(skip_serializing_if = "Option::is_none")]
pub not: Option<Box<Schema>>,
/// The `if` keyword.
///
/// See [JSON Schema 9.2.2.1. "if"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).
#[serde(rename = "if", skip_serializing_if = "Option::is_none")]
pub if_schema: Option<Box<Schema>>,
/// The `then` keyword.
///
/// See [JSON Schema 9.2.2.2. "then"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).
#[serde(rename = "then", skip_serializing_if = "Option::is_none")]
pub then_schema: Option<Box<Schema>>,
/// The `else` keyword.
///
/// See [JSON Schema 9.2.2.3. "else"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).
#[serde(rename = "else", skip_serializing_if = "Option::is_none")]
pub else_schema: Option<Box<Schema>>,
}
/// Properties of a [`SchemaObject`] which define validation assertions for numbers.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct NumberValidation {
/// The `multipleOf` keyword.
///
/// See [JSON Schema Validation 6.2.1. "multipleOf"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub multiple_of: Option<f64>,
/// The `maximum` keyword.
///
/// See [JSON Schema Validation 6.2.2. "maximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub maximum: Option<f64>,
/// The `exclusiveMaximum` keyword.
///
/// See [JSON Schema Validation 6.2.3. "exclusiveMaximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub exclusive_maximum: Option<f64>,
/// The `minimum` keyword.
///
/// See [JSON Schema Validation 6.2.4. "minimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.4).
#[serde(skip_serializing_if = "Option::is_none")]
pub minimum: Option<f64>,
/// The `exclusiveMinimum` keyword.
///
/// See [JSON Schema Validation 6.2.5. "exclusiveMinimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.5).
#[serde(skip_serializing_if = "Option::is_none")]
pub exclusive_minimum: Option<f64>,
}
/// Properties of a [`SchemaObject`] which define validation assertions for strings.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct StringValidation {
/// The `maxLength` keyword.
///
/// See [JSON Schema Validation 6.3.1. "maxLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub max_length: Option<u32>,
/// The `minLength` keyword.
///
/// See [JSON Schema Validation 6.3.2. "minLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub min_length: Option<u32>,
/// The `pattern` keyword.
///
/// See [JSON Schema Validation 6.3.3. "pattern"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub pattern: Option<String>,
}
/// Properties of a [`SchemaObject`] which define validation assertions for arrays.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct ArrayValidation {
/// The `items` keyword.
///
/// See [JSON Schema 9.3.1.1. "items"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub items: Option<SingleOrVec<Schema>>,
/// The `additionalItems` keyword.
///
/// See [JSON Schema 9.3.1.2. "additionalItems"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_items: Option<Box<Schema>>,
/// The `maxItems` keyword.
///
/// See [JSON Schema Validation 6.4.1. "maxItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub max_items: Option<u32>,
/// The `minItems` keyword.
///
/// See [JSON Schema Validation 6.4.2. "minItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub min_items: Option<u32>,
/// The `uniqueItems` keyword.
///
/// See [JSON Schema Validation 6.4.3. "uniqueItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub unique_items: Option<bool>,
/// The `contains` keyword.
///
/// See [JSON Schema 9.3.1.4. "contains"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).
#[serde(skip_serializing_if = "Option::is_none")]
pub contains: Option<Box<Schema>>,
}
/// Properties of a [`SchemaObject`] which define validation assertions for objects.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", default)]
pub struct ObjectValidation {
/// The `maxProperties` keyword.
///
/// See [JSON Schema Validation 6.5.1. "maxProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.1).
#[serde(skip_serializing_if = "Option::is_none")]
pub max_properties: Option<u32>,
/// The `minProperties` keyword.
///
/// See [JSON Schema Validation 6.5.2. "minProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub min_properties: Option<u32>,
/// The `required` keyword.
///
/// See [JSON Schema Validation 6.5.3. "required"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.3).
#[serde(skip_serializing_if = "Set::is_empty")]
pub required: Set<String>,
/// The `properties` keyword.
///
/// See [JSON Schema 9.3.2.1. "properties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).
#[serde(skip_serializing_if = "Map::is_empty")]
pub properties: Map<String, Schema>,
/// The `patternProperties` keyword.
///
/// See [JSON Schema 9.3.2.2. "patternProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.2).
#[serde(skip_serializing_if = "Map::is_empty")]
pub pattern_properties: Map<String, Schema>,
/// The `additionalProperties` keyword.
///
/// See [JSON Schema 9.3.2.3. "additionalProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_properties: Option<Box<Schema>>,
/// The `propertyNames` keyword.
///
/// See [JSON Schema 9.3.2.5. "propertyNames"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).
#[serde(skip_serializing_if = "Option::is_none")]
pub property_names: Option<Box<Schema>>,
}
/// The possible types of values in JSON Schema documents.
///
/// See [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase")]
pub enum InstanceType {
Null,
Boolean,
Object,
Array,
Number,
String,
Integer,
}
/// A type which can be serialized as a single item, or multiple items.
///
/// In some contexts, a `Single` may be semantically distinct from a `Vec` containing only item.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "impl_json_schema", derive(JsonSchema))]
#[serde(untagged)]
pub enum SingleOrVec<T> {
Single(Box<T>),
Vec(Vec<T>),
}
impl<T> From<T> for SingleOrVec<T> {
fn from(single: T) -> Self {
SingleOrVec::Single(Box::new(single))
}
}
impl<T> From<Vec<T>> for SingleOrVec<T> {
fn from(vec: Vec<T>) -> Self {
SingleOrVec::Vec(vec)
}
}
impl<T: PartialEq> SingleOrVec<T> {
/// Returns `true` if `self` is either a `Single` equal to `x`, or a `Vec` containing `x`.
///
/// # Examples
///
/// ```
/// use schemars::schema::SingleOrVec;
///
/// let s = SingleOrVec::from(10);
/// assert!(s.contains(&10));
/// assert!(!s.contains(&20));
///
/// let v = SingleOrVec::from(vec![10, 20]);
/// assert!(v.contains(&10));
/// assert!(v.contains(&20));
/// assert!(!v.contains(&30));
/// ```
pub fn contains(&self, x: &T) -> bool {
match self {
SingleOrVec::Single(s) => s.deref() == x,
SingleOrVec::Vec(v) => v.contains(x),
}
}
}

509
vendor/schemars/src/ser.rs vendored Normal file
View File

@@ -0,0 +1,509 @@
use crate::schema::*;
use crate::JsonSchema;
use crate::{r#gen::SchemaGenerator, Map};
use serde_json::{Error, Value};
use std::{convert::TryInto, fmt::Display};
pub(crate) struct Serializer<'a> {
pub(crate) generator: &'a mut SchemaGenerator,
pub(crate) include_title: bool,
}
pub(crate) struct SerializeSeq<'a> {
generator: &'a mut SchemaGenerator,
items: Option<Schema>,
}
pub(crate) struct SerializeTuple<'a> {
generator: &'a mut SchemaGenerator,
items: Vec<Schema>,
title: &'static str,
}
pub(crate) struct SerializeMap<'a> {
generator: &'a mut SchemaGenerator,
properties: Map<String, Schema>,
current_key: Option<String>,
title: &'static str,
}
macro_rules! forward_to_subschema_for {
($fn:ident, $ty:ty) => {
fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
Ok(self.generator.subschema_for::<$ty>())
}
};
}
macro_rules! return_instance_type {
($fn:ident, $ty:ty, $instance_type:ident) => {
fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
Ok(SchemaObject {
instance_type: Some(InstanceType::$instance_type.into()),
..Default::default()
}
.into())
}
};
}
impl<'a> serde::Serializer for Serializer<'a> {
type Ok = Schema;
type Error = Error;
type SerializeSeq = SerializeSeq<'a>;
type SerializeTuple = SerializeTuple<'a>;
type SerializeTupleStruct = SerializeTuple<'a>;
type SerializeTupleVariant = Self;
type SerializeMap = SerializeMap<'a>;
type SerializeStruct = SerializeMap<'a>;
type SerializeStructVariant = Self;
return_instance_type!(serialize_i8, i8, Integer);
return_instance_type!(serialize_i16, i16, Integer);
return_instance_type!(serialize_i32, i32, Integer);
return_instance_type!(serialize_i64, i64, Integer);
return_instance_type!(serialize_i128, i128, Integer);
return_instance_type!(serialize_u8, u8, Integer);
return_instance_type!(serialize_u16, u16, Integer);
return_instance_type!(serialize_u32, u32, Integer);
return_instance_type!(serialize_u64, u64, Integer);
return_instance_type!(serialize_u128, u128, Integer);
return_instance_type!(serialize_f32, f32, Number);
return_instance_type!(serialize_f64, f64, Number);
forward_to_subschema_for!(serialize_bool, bool);
forward_to_subschema_for!(serialize_char, char);
forward_to_subschema_for!(serialize_str, &str);
forward_to_subschema_for!(serialize_bytes, &[u8]);
fn collect_str<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: Display,
{
Ok(self.generator.subschema_for::<&str>())
}
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
where
K: serde::Serialize,
V: serde::Serialize,
I: IntoIterator<Item = (K, V)>,
{
let value_schema = iter
.into_iter()
.try_fold(None, |acc, (_, v)| {
if acc == Some(Schema::Bool(true)) {
return Ok(acc);
}
let schema = v.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
Ok(match &acc {
None => Some(schema),
Some(items) if items != &schema => Some(Schema::Bool(true)),
_ => acc,
})
})?
.unwrap_or(Schema::Bool(true));
Ok(SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
additional_properties: Some(Box::new(value_schema)),
..ObjectValidation::default()
})),
..SchemaObject::default()
}
.into())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Ok(self.generator.subschema_for::<Option<Value>>())
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
self.serialize_none()
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
// FIXME nasty duplication of `impl JsonSchema for Option<T>`
fn add_null_type(instance_type: &mut SingleOrVec<InstanceType>) {
match instance_type {
SingleOrVec::Single(ty) if **ty != InstanceType::Null => {
*instance_type = vec![**ty, InstanceType::Null].into()
}
SingleOrVec::Vec(ty) if !ty.contains(&InstanceType::Null) => {
ty.push(InstanceType::Null)
}
_ => {}
};
}
let mut schema = value.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
if self.generator.settings().option_add_null_type {
schema = match schema {
Schema::Bool(true) => Schema::Bool(true),
Schema::Bool(false) => <()>::json_schema(self.generator),
Schema::Object(SchemaObject {
instance_type: Some(ref mut instance_type),
..
}) => {
add_null_type(instance_type);
schema
}
schema => SchemaObject {
subschemas: Some(Box::new(SubschemaValidation {
any_of: Some(vec![schema, <()>::json_schema(self.generator)]),
..Default::default()
})),
..Default::default()
}
.into(),
}
}
if self.generator.settings().option_nullable {
let mut schema_obj = schema.into_object();
schema_obj
.extensions
.insert("nullable".to_owned(), serde_json::json!(true));
schema = Schema::Object(schema_obj);
};
Ok(schema)
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Ok(self.generator.subschema_for::<()>())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Ok(Schema::Bool(true))
}
fn serialize_newtype_struct<T: ?Sized>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
let include_title = self.include_title;
let mut result = value.serialize(self);
if include_title {
if let Ok(Schema::Object(ref mut object)) = result {
object.metadata().title = Some(name.to_string());
}
}
result
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
Ok(Schema::Bool(true))
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Ok(SerializeSeq {
generator: self.generator,
items: None,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Ok(SerializeTuple {
generator: self.generator,
items: Vec::with_capacity(len),
title: "",
})
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
let title = if self.include_title { name } else { "" };
Ok(SerializeTuple {
generator: self.generator,
items: Vec::with_capacity(len),
title,
})
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Ok(self)
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Ok(SerializeMap {
generator: self.generator,
properties: Map::new(),
current_key: None,
title: "",
})
}
fn serialize_struct(
self,
name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
let title = if self.include_title { name } else { "" };
Ok(SerializeMap {
generator: self.generator,
properties: Map::new(),
current_key: None,
title,
})
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Ok(self)
}
}
impl serde::ser::SerializeTupleVariant for Serializer<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Schema::Bool(true))
}
}
impl serde::ser::SerializeStructVariant for Serializer<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
_key: &'static str,
_value: &T,
) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Schema::Bool(true))
}
}
impl serde::ser::SerializeSeq for SerializeSeq<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
if self.items != Some(Schema::Bool(true)) {
let schema = value.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
match &self.items {
None => self.items = Some(schema),
Some(items) => {
if items != &schema {
self.items = Some(Schema::Bool(true))
}
}
}
}
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let items = self.items.unwrap_or(Schema::Bool(true));
Ok(SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(items.into()),
..ArrayValidation::default()
})),
..SchemaObject::default()
}
.into())
}
}
impl serde::ser::SerializeTuple for SerializeTuple<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
let schema = value.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
self.items.push(schema);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let len = self.items.len().try_into().ok();
let mut schema = SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(SingleOrVec::Vec(self.items)),
max_items: len,
min_items: len,
..ArrayValidation::default()
})),
..SchemaObject::default()
};
if !self.title.is_empty() {
schema.metadata().title = Some(self.title.to_owned());
}
Ok(schema.into())
}
}
impl serde::ser::SerializeTupleStruct for SerializeTuple<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
serde::ser::SerializeTuple::serialize_element(self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
serde::ser::SerializeTuple::end(self)
}
}
impl serde::ser::SerializeMap for SerializeMap<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
// FIXME this is too lenient - we should return an error if serde_json
// doesn't allow T to be a key of a map.
let json = serde_json::to_string(key)?;
self.current_key = Some(
json.trim_start_matches('"')
.trim_end_matches('"')
.to_string(),
);
Ok(())
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
let key = self.current_key.take().unwrap_or_default();
let schema = value.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
self.properties.insert(key, schema);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let mut schema = SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
properties: self.properties,
..ObjectValidation::default()
})),
..SchemaObject::default()
};
if !self.title.is_empty() {
schema.metadata().title = Some(self.title.to_owned());
}
Ok(schema.into())
}
}
impl serde::ser::SerializeStruct for SerializeMap<'_> {
type Ok = Schema;
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: serde::Serialize,
{
let prop_schema = value.serialize(Serializer {
generator: self.generator,
include_title: false,
})?;
self.properties.insert(key.to_string(), prop_schema);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
serde::ser::SerializeMap::end(self)
}
}

212
vendor/schemars/src/visit.rs vendored Normal file
View File

@@ -0,0 +1,212 @@
/*!
Contains the [`Visitor`] trait, used to recursively modify a constructed schema and its subschemas.
Sometimes you may want to apply a change to a schema, as well as all schemas contained within it.
The easiest way to achieve this is by defining a type that implements [`Visitor`].
All methods of `Visitor` have a default implementation that makes no change but recursively visits all subschemas.
When overriding one of these methods, you will *usually* want to still call this default implementation.
# Example
To add a custom property to all schemas:
```
use schemars::schema::SchemaObject;
use schemars::visit::{Visitor, visit_schema_object};
pub struct MyVisitor;
impl Visitor for MyVisitor {
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
// First, make our change to this schema
schema.extensions.insert("my_property".to_string(), serde_json::json!("hello world"));
// Then delegate to default implementation to visit any subschemas
visit_schema_object(self, schema);
}
}
```
*/
use crate::schema::{RootSchema, Schema, SchemaObject, SingleOrVec};
/// Trait used to recursively modify a constructed schema and its subschemas.
pub trait Visitor {
/// Override this method to modify a [`RootSchema`] and (optionally) its subschemas.
///
/// When overriding this method, you will usually want to call the [`visit_root_schema`] function to visit subschemas.
fn visit_root_schema(&mut self, root: &mut RootSchema) {
visit_root_schema(self, root)
}
/// Override this method to modify a [`Schema`] and (optionally) its subschemas.
///
/// When overriding this method, you will usually want to call the [`visit_schema`] function to visit subschemas.
fn visit_schema(&mut self, schema: &mut Schema) {
visit_schema(self, schema)
}
/// Override this method to modify a [`SchemaObject`] and (optionally) its subschemas.
///
/// When overriding this method, you will usually want to call the [`visit_schema_object`] function to visit subschemas.
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
visit_schema_object(self, schema)
}
}
/// Visits all subschemas of the [`RootSchema`].
pub fn visit_root_schema<V: Visitor + ?Sized>(v: &mut V, root: &mut RootSchema) {
v.visit_schema_object(&mut root.schema);
visit_map_values(v, &mut root.definitions);
}
/// Visits all subschemas of the [`Schema`].
pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
if let Schema::Object(schema) = schema {
v.visit_schema_object(schema)
}
}
/// Visits all subschemas of the [`SchemaObject`].
pub fn visit_schema_object<V: Visitor + ?Sized>(v: &mut V, schema: &mut SchemaObject) {
if let Some(sub) = &mut schema.subschemas {
visit_vec(v, &mut sub.all_of);
visit_vec(v, &mut sub.any_of);
visit_vec(v, &mut sub.one_of);
visit_box(v, &mut sub.not);
visit_box(v, &mut sub.if_schema);
visit_box(v, &mut sub.then_schema);
visit_box(v, &mut sub.else_schema);
}
if let Some(arr) = &mut schema.array {
visit_single_or_vec(v, &mut arr.items);
visit_box(v, &mut arr.additional_items);
visit_box(v, &mut arr.contains);
}
if let Some(obj) = &mut schema.object {
visit_map_values(v, &mut obj.properties);
visit_map_values(v, &mut obj.pattern_properties);
visit_box(v, &mut obj.additional_properties);
visit_box(v, &mut obj.property_names);
}
}
fn visit_box<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<Box<Schema>>) {
if let Some(s) = target {
v.visit_schema(s)
}
}
fn visit_vec<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<Vec<Schema>>) {
if let Some(vec) = target {
for s in vec {
v.visit_schema(s)
}
}
}
fn visit_map_values<V: Visitor + ?Sized>(v: &mut V, target: &mut crate::Map<String, Schema>) {
for s in target.values_mut() {
v.visit_schema(s)
}
}
fn visit_single_or_vec<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<SingleOrVec<Schema>>) {
match target {
None => {}
Some(SingleOrVec::Single(s)) => v.visit_schema(s),
Some(SingleOrVec::Vec(vec)) => {
for s in vec {
v.visit_schema(s)
}
}
}
}
/// This visitor will replace all boolean JSON Schemas with equivalent object schemas.
///
/// This is useful for dialects of JSON Schema (e.g. OpenAPI 3.0) that do not support booleans as schemas.
#[derive(Debug, Clone)]
pub struct ReplaceBoolSchemas {
/// When set to `true`, a schema's `additionalProperties` property will not be changed from a boolean.
pub skip_additional_properties: bool,
}
impl Visitor for ReplaceBoolSchemas {
fn visit_schema(&mut self, schema: &mut Schema) {
visit_schema(self, schema);
if let Schema::Bool(b) = *schema {
*schema = Schema::Bool(b).into_object().into()
}
}
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
if self.skip_additional_properties {
if let Some(obj) = &mut schema.object {
if let Some(ap) = &obj.additional_properties {
if let Schema::Bool(_) = ap.as_ref() {
let additional_properties = obj.additional_properties.take();
visit_schema_object(self, schema);
schema.object().additional_properties = additional_properties;
return;
}
}
}
}
visit_schema_object(self, schema);
}
}
/// This visitor will restructure JSON Schema objects so that the `$ref` property will never appear alongside any other properties.
///
/// This is useful for dialects of JSON Schema (e.g. Draft 7) that do not support other properties alongside `$ref`.
#[derive(Debug, Clone)]
pub struct RemoveRefSiblings;
impl Visitor for RemoveRefSiblings {
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
visit_schema_object(self, schema);
if let Some(reference) = schema.reference.take() {
if schema == &SchemaObject::default() {
schema.reference = Some(reference);
} else {
let ref_schema = Schema::new_ref(reference);
let all_of = &mut schema.subschemas().all_of;
match all_of {
Some(vec) => vec.push(ref_schema),
None => *all_of = Some(vec![ref_schema]),
}
}
}
}
}
/// This visitor will remove the `examples` schema property and (if present) set its first value as the `example` property.
///
/// This is useful for dialects of JSON Schema (e.g. OpenAPI 3.0) that do not support the `examples` property.
#[derive(Debug, Clone)]
pub struct SetSingleExample {
/// When set to `true`, the `examples` property will not be removed, but its first value will still be copied to `example`.
pub retain_examples: bool,
}
impl Visitor for SetSingleExample {
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
visit_schema_object(self, schema);
let first_example = schema.metadata.as_mut().and_then(|m| {
if self.retain_examples {
m.examples.first().cloned()
} else {
m.examples.drain(..).next()
}
});
if let Some(example) = first_example {
schema.extensions.insert("example".to_owned(), example);
}
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,3 @@
# Actual Generated Schemas
If a test fails because a generated schema did not match the expected JSON, then the actual schema will be written to a JSON file in this directory.

22
vendor/schemars/tests/arrayvec.rs vendored Normal file
View File

@@ -0,0 +1,22 @@
mod util;
use util::*;
#[test]
fn arrayvec05() -> TestResult {
test_default_generated_schema::<arrayvec05::ArrayVec<[i32; 16]>>("arrayvec")
}
#[test]
fn arrayvec05_string() -> TestResult {
test_default_generated_schema::<arrayvec05::ArrayString<[u8; 16]>>("arrayvec_string")
}
#[test]
fn arrayvec07() -> TestResult {
test_default_generated_schema::<arrayvec07::ArrayVec<i32, 16>>("arrayvec")
}
#[test]
fn arrayvec07_string() -> TestResult {
test_default_generated_schema::<arrayvec07::ArrayString<16>>("arrayvec_string")
}

32
vendor/schemars/tests/bound.rs vendored Normal file
View File

@@ -0,0 +1,32 @@
mod util;
use std::marker::PhantomData;
use schemars::JsonSchema;
use util::*;
struct MyIterator;
impl Iterator for MyIterator {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
// The default trait bounds would require T to implement JsonSchema,
// which MyIterator does not.
#[derive(JsonSchema)]
#[schemars(bound = "T::Item: JsonSchema", rename = "MyContainer")]
pub struct MyContainer<T>
where
T: Iterator,
{
pub associated: T::Item,
pub generic: PhantomData<T>,
}
#[test]
fn manual_bound_set() -> TestResult {
test_default_generated_schema::<MyContainer<MyIterator>>("bound")
}

8
vendor/schemars/tests/bytes.rs vendored Normal file
View File

@@ -0,0 +1,8 @@
mod util;
use bytes::{Bytes, BytesMut};
use util::*;
#[test]
fn bytes() -> TestResult {
test_default_generated_schema::<(Bytes, BytesMut)>("bytes")
}

19
vendor/schemars/tests/chrono.rs vendored Normal file
View File

@@ -0,0 +1,19 @@
mod util;
use chrono::prelude::*;
use schemars::JsonSchema;
use util::*;
#[allow(dead_code)]
#[derive(JsonSchema)]
struct ChronoTypes {
weekday: Weekday,
date_time: DateTime<Utc>,
naive_date: NaiveDate,
naive_date_time: NaiveDateTime,
naive_time: NaiveTime,
}
#[test]
fn chrono_types() -> TestResult {
test_default_generated_schema::<ChronoTypes>("chrono-types")
}

20
vendor/schemars/tests/crate_alias.rs vendored Normal file
View File

@@ -0,0 +1,20 @@
mod util;
use ::schemars as not_schemars;
use util::*;
#[allow(unused_imports)]
use std as schemars;
#[allow(dead_code)]
#[derive(not_schemars::JsonSchema)]
#[schemars(crate = "not_schemars")]
struct Struct {
/// This is a document
foo: i32,
bar: bool,
}
#[test]
fn test_crate_alias() -> TestResult {
test_default_generated_schema::<Struct>("crate_alias")
}

17
vendor/schemars/tests/decimal.rs vendored Normal file
View File

@@ -0,0 +1,17 @@
mod util;
use util::*;
#[test]
fn rust_decimal() -> TestResult {
test_default_generated_schema::<rust_decimal::Decimal>("rust_decimal")
}
#[test]
fn bigdecimal03() -> TestResult {
test_default_generated_schema::<bigdecimal03::BigDecimal>("bigdecimal03")
}
#[test]
fn bigdecimal04() -> TestResult {
test_default_generated_schema::<bigdecimal04::BigDecimal>("bigdecimal04")
}

59
vendor/schemars/tests/default.rs vendored Normal file
View File

@@ -0,0 +1,59 @@
mod util;
use schemars::JsonSchema;
use util::*;
fn is_default<T: Default + PartialEq>(value: &T) -> bool {
value == &T::default()
}
fn ten_and_true() -> MyStruct2 {
MyStruct2 {
my_int: 10,
my_bool: true,
}
}
fn six() -> i32 {
6
}
fn custom_serialize<S>(value: &MyStruct2, ser: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.collect_str(&format_args!("i:{} b:{}", value.my_int, value.my_bool))
}
#[allow(dead_code)]
#[derive(Default, JsonSchema)]
#[serde(default)]
struct MyStruct {
my_int: i32,
my_bool: bool,
my_optional_string: Option<String>,
#[serde(serialize_with = "custom_serialize")]
my_struct2: MyStruct2,
#[serde(
serialize_with = "custom_serialize",
skip_serializing_if = "is_default"
)]
my_struct2_default_skipped: MyStruct2,
not_serialize: NotSerialize,
}
#[allow(dead_code)]
#[derive(Default, JsonSchema, PartialEq)]
#[serde(default = "ten_and_true")]
struct MyStruct2 {
#[serde(default = "six")]
my_int: i32,
my_bool: bool,
}
#[derive(Default, JsonSchema)]
struct NotSerialize;
#[test]
fn schema_default_values() -> TestResult {
test_default_generated_schema::<MyStruct>("default")
}

39
vendor/schemars/tests/deprecated.rs vendored Normal file
View File

@@ -0,0 +1,39 @@
#![allow(deprecated)]
mod util;
use schemars::JsonSchema;
use util::*;
#[allow(dead_code)]
#[derive(JsonSchema)]
#[deprecated]
struct DeprecatedStruct {
foo: i32,
#[deprecated]
deprecated_field: bool,
}
#[test]
fn deprecated_struct() -> TestResult {
test_default_generated_schema::<DeprecatedStruct>("deprecated-struct")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[deprecated]
enum DeprecatedEnum {
Unit,
#[deprecated]
DeprecatedUnitVariant,
#[deprecated]
DeprecatedStructVariant {
foo: i32,
#[deprecated]
deprecated_field: bool,
},
}
#[test]
fn deprecated_enum() -> TestResult {
test_default_generated_schema::<DeprecatedEnum>("deprecated-enum")
}

23
vendor/schemars/tests/dereference.rs vendored Normal file
View File

@@ -0,0 +1,23 @@
use schemars::{r#gen::SchemaGenerator, JsonSchema};
use std::ptr;
#[allow(dead_code)]
#[derive(JsonSchema)]
struct Struct {
foo: i32,
bar: bool,
}
#[test]
fn dereference_struct() {
let mut generator = SchemaGenerator::default();
let struct_ref_schema = generator.subschema_for::<Struct>();
let struct_schema = generator.definitions().get(&<Struct>::schema_name()).unwrap();
assert!(struct_ref_schema.is_ref());
assert!(!struct_schema.is_ref());
let dereferenced = generator.dereference(&struct_ref_schema);
assert!(dereferenced.is_some());
assert!(ptr::eq(dereferenced.unwrap(), struct_schema));
}

91
vendor/schemars/tests/docs.rs vendored Normal file
View File

@@ -0,0 +1,91 @@
mod util;
use schemars::{r#gen::SchemaSettings, JsonSchema};
use util::*;
#[allow(dead_code)]
#[derive(JsonSchema)]
/**
*
* # This is the struct's title
*
* This is the struct's description.
*
*/
struct MyStruct {
/// # An integer
my_int: i32,
my_undocumented_bool: bool,
/// A unit struct instance
my_unit: MyUnitStruct,
}
/// # A Unit
///
#[derive(JsonSchema)]
struct MyUnitStruct;
#[allow(dead_code)]
#[doc = " # This is the enum's title "]
#[doc = " This is "]
#[derive(JsonSchema)]
#[doc = " the enum's description."]
enum MyEnum {
UndocumentedUnit,
UndocumentedUnit2,
/// This comment is included in the generated schema :)
DocumentedUnit,
/// ## Complex variant
/// This is a struct-like variant.
Complex {
/// ### A nullable string
///
/// This field is a nullable string.
///
/// This
///is
/// the second
/// line!
///
///
///
///
/// And this is the third!
my_nullable_string: Option<String>,
},
}
#[test]
fn doc_comments_struct() -> TestResult {
test_default_generated_schema::<MyStruct>("doc_comments_struct")
}
#[test]
fn doc_comments_struct_ref_siblings() -> TestResult {
let settings = SchemaSettings::draft2019_09();
test_generated_schema::<MyStruct>("doc_comments_struct_ref_siblings", settings)
}
#[test]
fn doc_comments_enum() -> TestResult {
test_default_generated_schema::<MyEnum>("doc_comments_enum")
}
/// # OverrideDocs struct
/// This description should be overridden
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(description = "New description")]
struct OverrideDocs {
/// # Overridden
#[schemars(title = "My integer", description = "This is an i32")]
my_int: i32,
/// # Overridden
/// Also overridden
#[schemars(title = "", description = "")]
my_undocumented_bool: bool,
}
#[test]
fn doc_comments_override() -> TestResult {
test_default_generated_schema::<OverrideDocs>("doc_comments_override")
}

8
vendor/schemars/tests/either.rs vendored Normal file
View File

@@ -0,0 +1,8 @@
mod util;
use either::Either;
use util::*;
#[test]
fn either() -> TestResult {
test_default_generated_schema::<Either<i32, Either<bool, ()>>>("either")
}

146
vendor/schemars/tests/enum.rs vendored Normal file
View File

@@ -0,0 +1,146 @@
mod util;
use schemars::{JsonSchema, Map};
use util::*;
// Ensure that schemars_derive uses the full path to std::string::String
pub struct String;
#[derive(JsonSchema)]
struct UnitStruct;
#[allow(dead_code)]
#[derive(JsonSchema)]
struct Struct {
foo: i32,
bar: bool,
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(rename_all = "camelCase")]
enum External {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
UnitTwo,
Tuple(i32, bool),
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_external_tag() -> TestResult {
test_default_generated_schema::<External>("enum-external")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "typeProperty")]
enum Internal {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
UnitTwo,
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_internal_tag() -> TestResult {
test_default_generated_schema::<Internal>("enum-internal")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(untagged)]
enum Untagged {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
Tuple(i32, bool),
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_untagged() -> TestResult {
test_default_generated_schema::<Untagged>("enum-untagged")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "t", content = "c")]
enum Adjacent {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
Tuple(i32, bool),
UnitTwo,
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_adjacent_tagged() -> TestResult {
test_default_generated_schema::<Adjacent>("enum-adjacent-tagged")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "typeProperty")]
enum SimpleInternal {
A,
B,
C,
}
#[test]
fn enum_simple_internal_tag() -> TestResult {
test_default_generated_schema::<SimpleInternal>("enum-simple-internal")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
enum SoundOfMusic {
/// # A deer
///
/// A female deer
Do,
/// A drop of golden sun
Re,
/// A name I call myself
Mi,
}
#[test]
fn enum_unit_with_doc_comments() -> TestResult {
test_default_generated_schema::<SoundOfMusic>("enum-unit-doc")
}
#[derive(JsonSchema)]
enum NoVariants {}
#[test]
fn enum_no_variants() -> TestResult {
test_default_generated_schema::<NoVariants>("no-variants")
}

View File

@@ -0,0 +1,125 @@
mod util;
use schemars::{JsonSchema, Map};
use util::*;
// Ensure that schemars_derive uses the full path to std::string::String
pub struct String;
#[derive(JsonSchema)]
struct UnitStruct;
#[allow(dead_code)]
#[derive(JsonSchema)]
struct Struct {
foo: i32,
bar: bool,
}
// Outer container should always have additionalProperties: false
// `Struct` variant should have additionalProperties: false
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
enum External {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
UnitTwo,
Tuple(i32, bool),
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_external_tag() -> TestResult {
test_default_generated_schema::<External>("enum-external-duf")
}
// Only `Struct` variant should have additionalProperties: false
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "typeProperty", deny_unknown_fields)]
enum Internal {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
UnitTwo,
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_internal_tag() -> TestResult {
test_default_generated_schema::<Internal>("enum-internal-duf")
}
// Only `Struct` variant should have additionalProperties: false
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(untagged, deny_unknown_fields)]
enum Untagged {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
Tuple(i32, bool),
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_untagged() -> TestResult {
test_default_generated_schema::<Untagged>("enum-untagged-duf")
}
// Outer container and `Struct` variant should have additionalProperties: false
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "t", content = "c", deny_unknown_fields)]
enum Adjacent {
UnitOne,
StringMap(Map<&'static str, &'static str>),
UnitStructNewType(UnitStruct),
StructNewType(Struct),
Struct {
foo: i32,
bar: bool,
},
Tuple(i32, bool),
UnitTwo,
#[schemars(with = "i32")]
WithInt,
}
#[test]
fn enum_adjacent_tagged() -> TestResult {
test_default_generated_schema::<Adjacent>("enum-adjacent-tagged-duf")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(tag = "typeProperty", deny_unknown_fields)]
enum SimpleInternal {
A,
B,
C,
}
#[test]
fn enum_simple_internal_tag() -> TestResult {
test_default_generated_schema::<SimpleInternal>("enum-simple-internal-duf")
}

35
vendor/schemars/tests/enum_repr.rs vendored Normal file
View File

@@ -0,0 +1,35 @@
mod util;
use schemars::JsonSchema_repr;
use util::*;
#[derive(JsonSchema_repr)]
#[repr(u8)]
pub enum Enum {
Zero,
One,
Five = 5,
Six,
Three = 3,
}
#[test]
fn enum_repr() -> TestResult {
test_default_generated_schema::<Enum>("enum-repr")
}
#[derive(JsonSchema_repr)]
#[repr(i64)]
#[serde(rename = "Renamed")]
/// Description from comment
pub enum EnumWithAttrs {
Zero,
One,
Five = 5,
Six,
Three = 3,
}
#[test]
fn enum_repr_with_attrs() -> TestResult {
test_default_generated_schema::<EnumWithAttrs>("enum-repr-with-attrs")
}

15
vendor/schemars/tests/enumset.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
mod util;
use enumset::{EnumSet, EnumSetType};
use schemars::JsonSchema;
use util::*;
#[derive(EnumSetType, JsonSchema)]
enum Foo {
Bar,
Baz,
}
#[test]
fn enumset() -> TestResult {
test_default_generated_schema::<EnumSet<Foo>>("enumset")
}

25
vendor/schemars/tests/examples.rs vendored Normal file
View File

@@ -0,0 +1,25 @@
mod util;
use schemars::JsonSchema;
use serde::Serialize;
use util::*;
#[derive(Default, JsonSchema, Serialize)]
#[schemars(example = "Struct::default", example = "null")]
struct Struct {
#[schemars(example = "eight", example = "null")]
foo: i32,
bar: bool,
#[schemars(example = "null")]
baz: Option<&'static str>,
}
fn eight() -> i32 {
8
}
fn null() {}
#[test]
fn examples() -> TestResult {
test_default_generated_schema::<Struct>("examples")
}

View File

@@ -0,0 +1,10 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Array_up_to_size_16_of_int32",
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"maxItems": 16
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "String",
"type": "string"
}

View File

@@ -0,0 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Decimal",
"type": "string",
"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
}

View File

@@ -0,0 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Decimal",
"type": "string",
"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
}

View File

@@ -0,0 +1,17 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyContainer",
"type": "object",
"required": [
"associated",
"generic"
],
"properties": {
"associated": {
"type": "string"
},
"generic": {
"type": "null"
}
}
}

View File

@@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Tuple_of_Array_of_uint8_and_Array_of_uint8",
"type": "array",
"items": [
{
"type": "array",
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0.0
}
},
{
"type": "array",
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0.0
}
}
],
"maxItems": 2,
"minItems": 2
}

View File

@@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ChronoTypes",
"type": "object",
"required": [
"date_time",
"naive_date",
"naive_date_time",
"naive_time",
"weekday"
],
"properties": {
"weekday": {
"type": "string",
"enum": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"
]
},
"date_time": {
"type": "string",
"format": "date-time"
},
"naive_date": {
"type": "string",
"format": "date"
},
"naive_date_time": {
"type": "string",
"format": "partial-date-time"
},
"naive_time": {
"type": "string",
"format": "partial-date-time"
}
}
}

View File

@@ -0,0 +1,19 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Struct",
"type": "object",
"required": [
"bar",
"foo"
],
"properties": {
"foo": {
"description": "This is a document",
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"
}
}
}

View File

@@ -0,0 +1,56 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"properties": {
"my_int": {
"default": 0,
"type": "integer",
"format": "int32"
},
"my_bool": {
"default": false,
"type": "boolean"
},
"my_optional_string": {
"default": null,
"type": [
"string",
"null"
]
},
"my_struct2": {
"default": "i:0 b:false",
"allOf": [
{
"$ref": "#/definitions/MyStruct2"
}
]
},
"my_struct2_default_skipped": {
"$ref": "#/definitions/MyStruct2"
},
"not_serialize": {
"$ref": "#/definitions/NotSerialize"
}
},
"definitions": {
"MyStruct2": {
"type": "object",
"properties": {
"my_int": {
"default": 6,
"type": "integer",
"format": "int32"
},
"my_bool": {
"default": true,
"type": "boolean"
}
}
},
"NotSerialize": {
"type": "null"
}
}
}

View File

@@ -0,0 +1,47 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "DeprecatedEnum",
"deprecated": true,
"oneOf": [
{
"type": "string",
"enum": [
"Unit"
]
},
{
"deprecated": true,
"type": "string",
"enum": [
"DeprecatedUnitVariant"
]
},
{
"deprecated": true,
"type": "object",
"required": [
"DeprecatedStructVariant"
],
"properties": {
"DeprecatedStructVariant": {
"type": "object",
"required": [
"deprecated_field",
"foo"
],
"properties": {
"deprecated_field": {
"deprecated": true,
"type": "boolean"
},
"foo": {
"type": "integer",
"format": "int32"
}
}
}
},
"additionalProperties": false
}
]
}

View File

@@ -0,0 +1,20 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "DeprecatedStruct",
"deprecated": true,
"type": "object",
"required": [
"deprecated_field",
"foo"
],
"properties": {
"foo": {
"type": "integer",
"format": "int32"
},
"deprecated_field": {
"deprecated": true,
"type": "boolean"
}
}
}

View File

@@ -0,0 +1,45 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "This is the enum's title",
"description": "This is the enum's description.",
"oneOf": [
{
"type": "string",
"enum": [
"UndocumentedUnit",
"UndocumentedUnit2"
]
},
{
"description": "This comment is included in the generated schema :)",
"type": "string",
"enum": [
"DocumentedUnit"
]
},
{
"title": "Complex variant",
"description": "This is a struct-like variant.",
"type": "object",
"required": [
"Complex"
],
"properties": {
"Complex": {
"type": "object",
"properties": {
"my_nullable_string": {
"title": "A nullable string",
"description": "This field is a nullable string.\n\nThis is the second line!\n\nAnd this is the third!",
"type": [
"string",
"null"
]
}
}
}
},
"additionalProperties": false
}
]
}

View File

@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OverrideDocs struct",
"description": "New description",
"type": "object",
"required": [
"my_int",
"my_undocumented_bool"
],
"properties": {
"my_int": {
"title": "My integer",
"description": "This is an i32",
"type": "integer",
"format": "int32"
},
"my_undocumented_bool": {
"type": "boolean"
}
}
}

View File

@@ -0,0 +1,35 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "This is the struct's title",
"description": "This is the struct's description.",
"type": "object",
"required": [
"my_int",
"my_undocumented_bool",
"my_unit"
],
"properties": {
"my_int": {
"title": "An integer",
"type": "integer",
"format": "int32"
},
"my_undocumented_bool": {
"type": "boolean"
},
"my_unit": {
"description": "A unit struct instance",
"allOf": [
{
"$ref": "#/definitions/MyUnitStruct"
}
]
}
},
"definitions": {
"MyUnitStruct": {
"title": "A Unit",
"type": "null"
}
}
}

View File

@@ -0,0 +1,31 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "This is the struct's title",
"description": "This is the struct's description.",
"type": "object",
"required": [
"my_int",
"my_undocumented_bool",
"my_unit"
],
"properties": {
"my_int": {
"title": "An integer",
"type": "integer",
"format": "int32"
},
"my_undocumented_bool": {
"type": "boolean"
},
"my_unit": {
"description": "A unit struct instance",
"$ref": "#/definitions/MyUnitStruct"
}
},
"definitions": {
"MyUnitStruct": {
"title": "A Unit",
"type": "null"
}
}
}

Some files were not shown because too many files have changed in this diff Show More