Compare commits
39 Commits
c6fc5f9123
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d6d0b10537 | |||
| 536125a4f4 | |||
| 3f17842a91 | |||
| 306f695617 | |||
| 47f79a9e1d | |||
| 277be04ae7 | |||
| 208d87df79 | |||
| 14c1955b15 | |||
| 97966c983a | |||
| bf2aada26f | |||
| 90ad7cfe45 | |||
| 235e32d29a | |||
| 8d1bf2dfb0 | |||
| 594fe4b1ae | |||
| bb6854f381 | |||
| 51a2717590 | |||
| 3eeeac6841 | |||
| c56760927c | |||
| caa4b23d5f | |||
| b5cf85adc7 | |||
| 934ca2c0dd | |||
| 88472ba02f | |||
| 87f942e440 | |||
| 07a955e654 | |||
| 805b46e164 | |||
| 94ec495057 | |||
| 8c93ab9b78 | |||
| 85e0c3abc5 | |||
| ebfe4d6e7c | |||
| 4f07dc2d73 | |||
| ed0d8e05f1 | |||
| bda9cc3fad | |||
| 960d4318ec | |||
| cc05d65eb9 | |||
| 115f907113 | |||
| 8f2b55fede | |||
| ca359c20e8 | |||
| 8044e1618d | |||
| 3f5ca27979 |
582
Cargo.lock
generated
582
Cargo.lock
generated
@@ -2,6 +2,17 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr"
|
||||
version = "0.11.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936697e9caf938eb2905036100edf8e1269da8291f8a02f5fe7b37073784eec0"
|
||||
dependencies = [
|
||||
"no-std-net",
|
||||
"psl",
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
@@ -11,18 +22,39 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
@@ -35,6 +67,21 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.4"
|
||||
@@ -72,6 +119,66 @@ dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.10"
|
||||
@@ -112,6 +219,37 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@@ -126,12 +264,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
@@ -139,6 +274,40 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
@@ -156,19 +325,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -177,12 +346,49 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "json-pointer"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fe841b94e719a482213cee19dd04927cf412f26d8dc84c5a446c081e49c2997"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonway"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "effcb749443c905fbaef49d214f8b1049c240e0adb7af9baa0e201e625e4f9de"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.4"
|
||||
@@ -204,6 +410,34 @@ version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "no-std-net"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[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.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "okapi"
|
||||
version = "0.7.0-rc.1"
|
||||
@@ -224,7 +458,7 @@ checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "openapi-parser"
|
||||
version = "0.1.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"env_logger",
|
||||
@@ -233,6 +467,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"valico",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -241,6 +476,56 @@ version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
@@ -267,13 +552,28 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ac31add97d7c393248c273c9f862bcfd396e870db1ff5dec63e0e707db82ae4"
|
||||
dependencies = [
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl-types"
|
||||
version = "2.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
@@ -283,6 +583,57 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.1"
|
||||
@@ -302,16 +653,16 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.7"
|
||||
version = "0.36.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
|
||||
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -344,6 +695,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.152"
|
||||
@@ -377,9 +734,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.91"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -399,6 +756,12 @@ dependencies = [
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
@@ -425,24 +788,194 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[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 = "unicode-bidi"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2"
|
||||
|
||||
[[package]]
|
||||
name = "uritemplate-next"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcde98d1fc3f528255b1ecb22fb688ee0d23deb672a8c57127df10b98b4bd18c"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
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"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valico"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "647856408e327686b6640397d19f60fac3e64c3bfaa6afc409da63ef7da45edb"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"base64",
|
||||
"chrono",
|
||||
"json-pointer",
|
||||
"jsonway",
|
||||
"percent-encoding",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uritemplate-next",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@@ -474,21 +1007,6 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
[package]
|
||||
name = "openapi-parser"
|
||||
version = "0.1.0"
|
||||
description = "Extract schemas definitions tree from OpenAPI documents"
|
||||
authors = ["Pierre Hubert <pierre.hubert.git@communiquons.org>"]
|
||||
license = "MIT"
|
||||
repository = "https://gitea.communiquons.org/pierre/OpenAPI-Parser"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -13,3 +17,4 @@ okapi = "0.7.0-rc.1"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_yaml = "0.9.17"
|
||||
serde_json = "1.0.91"
|
||||
valico = "3.6.1"
|
||||
|
||||
13
README.md
Normal file
13
README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# OPENAPI Parser
|
||||
Basic library to extract schema structures from OpenAPI 3 documents.
|
||||
|
||||
This crate can be used as a standalone binary:
|
||||
```bash
|
||||
cargo install openapi-parser
|
||||
```
|
||||
|
||||
|
||||
Create a tree graph for a schema:
|
||||
```bash
|
||||
openapi-parser -f openapi.yaml -s MySchema graph | dot -Tpng > dest.png
|
||||
```
|
||||
278
src/lib.rs
278
src/lib.rs
@@ -1,5 +1,48 @@
|
||||
use okapi::openapi3::{Components, OpenApi, SchemaObject};
|
||||
use okapi::schemars::schema::{InstanceType, Schema, SingleOrVec};
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub const REF_OBJECT: &str = "\u{0}\u{0}\u{0}\u{0}";
|
||||
|
||||
fn recurse_fix(mut v: &mut Value) {
|
||||
match &mut v {
|
||||
Value::Array(array) => {
|
||||
for item in array {
|
||||
recurse_fix(item);
|
||||
}
|
||||
}
|
||||
Value::Object(obj) => {
|
||||
for item in obj.iter_mut() {
|
||||
recurse_fix(item.1);
|
||||
}
|
||||
|
||||
if !obj.contains_key("examples") {
|
||||
if let Some(ex) = obj.get("example").cloned() {
|
||||
obj.insert("examples".to_string(), Value::Array(vec![ex]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse OpenAPI 3 schema, treating "example" field as "examples"
|
||||
///
|
||||
/// Otherwise, examples would be lost
|
||||
pub fn parse_schema_fix_example_issue(file_content: &str) -> OpenApi {
|
||||
let mut root = serde_yaml::from_str::<Value>(file_content)
|
||||
.expect("Failed to parse OpenAPI document as YAML document!");
|
||||
|
||||
if let Value::Object(root_obj) = &mut root {
|
||||
if let Some(components) = root_obj.get_mut("components") {
|
||||
recurse_fix(components);
|
||||
}
|
||||
}
|
||||
|
||||
parse_schema(&serde_yaml::to_string(&root).unwrap())
|
||||
}
|
||||
|
||||
/// Parse OpenAPI 3 schema
|
||||
pub fn parse_schema(file_content: &str) -> OpenApi {
|
||||
@@ -29,28 +72,91 @@ fn expect_schema_object(s: &Schema) -> &SchemaObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// Object child information
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct ObjectChild {
|
||||
/// The name of the field in the object
|
||||
pub name: String,
|
||||
/// The structure of the child
|
||||
pub node: TreeNode,
|
||||
}
|
||||
|
||||
/// The type of the schema
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum NodeType {
|
||||
/// NULL value
|
||||
Null,
|
||||
/// BOOLEAN value
|
||||
Boolean,
|
||||
Array { item: Box<TreeNode> },
|
||||
Object { children: Vec<TreeNode> },
|
||||
/// Array value
|
||||
Array {
|
||||
/// Schema information about the children of the array
|
||||
item: Box<TreeNode>,
|
||||
},
|
||||
/// Object value
|
||||
Object {
|
||||
/// Required filed for the object
|
||||
required: Option<Vec<String>>,
|
||||
/// The children of the object
|
||||
children: Vec<ObjectChild>,
|
||||
},
|
||||
/// String value
|
||||
String,
|
||||
/// Number value
|
||||
Number,
|
||||
/// Integer value
|
||||
Integer,
|
||||
}
|
||||
|
||||
impl NodeType {
|
||||
/// Specify if the type of the node allow children
|
||||
pub fn can_have_children(&self) -> bool {
|
||||
matches!(self, NodeType::Object { .. } | NodeType::Array { .. })
|
||||
}
|
||||
|
||||
/// Get a short symbol representing the type of value
|
||||
pub fn symbol(&self) -> &'static str {
|
||||
match self {
|
||||
NodeType::Null => "NULL",
|
||||
NodeType::Boolean => "Bool",
|
||||
NodeType::Array { .. } => "[]",
|
||||
NodeType::Object { .. } => "{}",
|
||||
NodeType::String => "str",
|
||||
NodeType::Number => "num",
|
||||
NodeType::Integer => "int",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parser schema structure node
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct TreeNode {
|
||||
/// The name of the schema
|
||||
pub name: String,
|
||||
/// The type of the schema
|
||||
#[serde(flatten)]
|
||||
pub r#type: NodeType,
|
||||
/// The description provided for the schema, if available
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
/// Examples values for the schema, if available
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub examples: Vec<String>,
|
||||
/// Discrete values of the schema, if specified
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub r#enum: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl TreeNode {
|
||||
/// Get the name of the schema, alongside with a symbol
|
||||
/// indicating its type
|
||||
pub fn print_name(&self) -> String {
|
||||
format!("{} {}", self.name, self.r#type.symbol())
|
||||
}
|
||||
|
||||
/// Merge two TreeNode
|
||||
pub fn merge_with(&self, other: &Self) -> Self {
|
||||
pub fn merge_with(self, other: Self) -> Self {
|
||||
if !matches!(self.r#type, NodeType::String | NodeType::Object { .. }) {
|
||||
panic!("Cannot merge!");
|
||||
}
|
||||
@@ -59,17 +165,36 @@ impl TreeNode {
|
||||
panic!("Cannot merge other!");
|
||||
}
|
||||
|
||||
let r#type = match (&self.r#type, &other.r#type) {
|
||||
let r#type = match (self.r#type, other.r#type) {
|
||||
(NodeType::String, NodeType::String) => NodeType::String,
|
||||
(NodeType::String, NodeType::Object { children })
|
||||
| (NodeType::Object { children }, NodeType::String) => NodeType::Object {
|
||||
children: children.clone(),
|
||||
},
|
||||
(NodeType::String, NodeType::Object { children, required })
|
||||
| (NodeType::Object { children, required }, NodeType::String) => {
|
||||
NodeType::Object { children, required }
|
||||
}
|
||||
|
||||
(NodeType::Object { children: c1 }, NodeType::Object { children: c2 }) => {
|
||||
let mut children = c1.clone();
|
||||
children.append(&mut c2.clone());
|
||||
NodeType::Object { children }
|
||||
(
|
||||
NodeType::Object {
|
||||
children: c1,
|
||||
required: r1,
|
||||
},
|
||||
NodeType::Object {
|
||||
children: mut c2,
|
||||
required: r2,
|
||||
},
|
||||
) => {
|
||||
let mut children = c1;
|
||||
children.append(&mut c2);
|
||||
|
||||
let mut required = r1.unwrap_or_default();
|
||||
required.append(&mut r2.unwrap_or_default());
|
||||
|
||||
NodeType::Object {
|
||||
children,
|
||||
required: match required.is_empty() {
|
||||
true => None,
|
||||
false => Some(required),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
(_, _) => unreachable!(),
|
||||
@@ -78,6 +203,102 @@ impl TreeNode {
|
||||
TreeNode {
|
||||
name: self.name.to_string(),
|
||||
r#type,
|
||||
description: other.description.or(self.description),
|
||||
examples: match other.examples.is_empty() {
|
||||
true => self.examples,
|
||||
false => other.examples,
|
||||
},
|
||||
r#enum: other.r#enum.or(self.r#enum),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get JSON example value
|
||||
pub fn example_value(&self, max_recursion: usize) -> Value {
|
||||
match &self.r#type {
|
||||
NodeType::Null => Value::Null,
|
||||
NodeType::Boolean => {
|
||||
Value::Bool(self.examples.first().map(|e| e == "true").unwrap_or(false))
|
||||
}
|
||||
|
||||
NodeType::Array { item } => Value::Array(vec![item.example_value(max_recursion)]),
|
||||
|
||||
NodeType::Object { children, .. } => {
|
||||
if max_recursion == 0 {
|
||||
return json!(HashMap::from([(REF_OBJECT.to_string(), &self.name)]));
|
||||
}
|
||||
|
||||
json!(children
|
||||
.iter()
|
||||
.map(|c| (c.name.clone(), c.node.example_value(max_recursion - 1)))
|
||||
.collect::<HashMap<String, serde_json::Value>>())
|
||||
}
|
||||
|
||||
NodeType::String => Value::String(
|
||||
self.examples
|
||||
.first()
|
||||
.map(|s| s.as_str().trim_matches('"'))
|
||||
.unwrap_or("string")
|
||||
.to_string(),
|
||||
),
|
||||
NodeType::Number => serde_json::json!(self
|
||||
.examples
|
||||
.first()
|
||||
.map(|s| s.parse::<f64>().expect("Failed to parse f64"))
|
||||
.unwrap_or(1.)),
|
||||
NodeType::Integer => serde_json::json!(self
|
||||
.examples
|
||||
.first()
|
||||
.map(|s| s.parse::<u64>().expect("Failed to parse f64"))
|
||||
.unwrap_or(0)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Turn object into JSON schema
|
||||
pub fn json_schema(&self) -> Value {
|
||||
valico::json_schema::builder::schema(|s| self.json_schema_inner(s)).into_json()
|
||||
}
|
||||
|
||||
fn json_schema_inner(&self, builder: &mut valico::json_schema::builder::Builder) {
|
||||
if let Some(description) = &self.description {
|
||||
builder.desc(description);
|
||||
}
|
||||
|
||||
match &self.r#type {
|
||||
NodeType::Null => {
|
||||
builder.null();
|
||||
}
|
||||
NodeType::Boolean => {
|
||||
builder.boolean();
|
||||
}
|
||||
|
||||
NodeType::Array { item } => {
|
||||
builder.array();
|
||||
builder.items_schema(|b| Self::json_schema_inner(item, b));
|
||||
}
|
||||
|
||||
NodeType::Object { children, required } => {
|
||||
if let Some(required) = required {
|
||||
builder.required(required.clone());
|
||||
}
|
||||
|
||||
builder.properties(|properties| {
|
||||
for child in children {
|
||||
properties.insert(&child.name, |child_prop| {
|
||||
Self::json_schema_inner(&child.node, child_prop);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
NodeType::String => {
|
||||
builder.string();
|
||||
}
|
||||
NodeType::Number => {
|
||||
builder.number();
|
||||
}
|
||||
NodeType::Integer => {
|
||||
builder.integer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,9 +334,10 @@ fn build_tree_schema(
|
||||
|
||||
for other in all_of.iter().skip(1) {
|
||||
let other = build_tree_schema(expect_schema_object(other), struct_name, components);
|
||||
tree = tree.merge_with(&other);
|
||||
tree = tree.merge_with(other);
|
||||
}
|
||||
|
||||
tree.name = struct_name.to_string();
|
||||
return tree;
|
||||
} else {
|
||||
panic!("Unsupported case!");
|
||||
@@ -132,18 +354,26 @@ fn build_tree_schema(
|
||||
InstanceType::Null => NodeType::Null,
|
||||
InstanceType::Boolean => NodeType::Boolean,
|
||||
InstanceType::Object => {
|
||||
let children = schema
|
||||
.object
|
||||
.as_ref()
|
||||
let object = schema.object.as_ref();
|
||||
let children = object
|
||||
.map(|s| s.properties.clone())
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|e| {
|
||||
let o = expect_schema_object(e.1);
|
||||
build_tree_schema(o, e.0, components)
|
||||
ObjectChild {
|
||||
name: e.0.to_string(),
|
||||
node: build_tree_schema(o, e.0, components),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
NodeType::Object { children }
|
||||
|
||||
let required = object
|
||||
.as_ref()
|
||||
.map(|o| &o.required)
|
||||
.map(|r| r.iter().map(|s| s.to_string()).collect());
|
||||
|
||||
NodeType::Object { children, required }
|
||||
}
|
||||
InstanceType::Array => {
|
||||
let item = expect_schema_object(expect_single(
|
||||
@@ -162,8 +392,20 @@ fn build_tree_schema(
|
||||
InstanceType::Integer => NodeType::Integer,
|
||||
};
|
||||
|
||||
let metadata = schema.metadata.clone().unwrap_or_default();
|
||||
|
||||
TreeNode {
|
||||
name: struct_name.to_string(),
|
||||
r#type,
|
||||
description: metadata.description,
|
||||
examples: metadata
|
||||
.examples
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
r#enum: schema
|
||||
.enum_values
|
||||
.as_ref()
|
||||
.map(|v| v.iter().map(|v| v.to_string()).collect()),
|
||||
}
|
||||
}
|
||||
|
||||
240
src/main.rs
240
src/main.rs
@@ -1,5 +1,10 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use openapi_parser::{build_tree, parse_schema};
|
||||
use openapi_parser::{
|
||||
build_tree, parse_schema, parse_schema_fix_example_issue, NodeType, ObjectChild, TreeNode,
|
||||
REF_OBJECT,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
/// Dump the tree structure of a schema element as dot file
|
||||
#[derive(Parser, Debug)]
|
||||
@@ -16,15 +21,39 @@ struct Args {
|
||||
#[arg(short, long, default_value = "Pet")]
|
||||
struct_name: String,
|
||||
|
||||
/// Treat "example" field as "examples"
|
||||
#[arg(long)]
|
||||
fix_example: bool,
|
||||
|
||||
/// The action to perform
|
||||
#[clap(subcommand)]
|
||||
action: Action,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[derive(Subcommand, Debug, Eq, PartialEq)]
|
||||
enum Action {
|
||||
/// Dump as JSON
|
||||
Json,
|
||||
|
||||
/// Dump JSON schema
|
||||
JsonSchema,
|
||||
|
||||
/// Dump JSON example
|
||||
JsonExample {
|
||||
/// Maximum recursion in dump
|
||||
#[arg(short, long, default_value_t = 100)]
|
||||
max_recursion: usize,
|
||||
},
|
||||
|
||||
/// Dump as Graphviz graph
|
||||
Graph,
|
||||
|
||||
/// Dump as Tex list
|
||||
Tex {
|
||||
/// Dump a single entry
|
||||
#[arg(short, long)]
|
||||
single: bool,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -37,10 +66,213 @@ fn main() {
|
||||
Some(path) => std::fs::read_to_string(path).expect("Unable to load schema file!"),
|
||||
};
|
||||
|
||||
let schema = parse_schema(&file_content);
|
||||
let tree = build_tree(&args.struct_name, schema.components.as_ref().unwrap());
|
||||
let schema = match args.fix_example {
|
||||
true => parse_schema_fix_example_issue(&file_content),
|
||||
false => parse_schema(&file_content),
|
||||
};
|
||||
let components = schema.components.as_ref().unwrap();
|
||||
|
||||
if args.action == (Action::Tex { single: false }) {
|
||||
for entry in components.schemas.keys() {
|
||||
let tree = build_tree(entry, components);
|
||||
println!("{}", tex_export(&tree));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let tree = build_tree(&args.struct_name, components);
|
||||
|
||||
match args.action {
|
||||
Action::Json => println!("{}", serde_json::to_string(&tree).unwrap()),
|
||||
Action::Graph => println!("{}", graphviz_export(&tree)),
|
||||
Action::Tex { .. } => println!("{}", tex_export(&tree)),
|
||||
Action::JsonSchema => println!("{}", json_schema(&tree)),
|
||||
Action::JsonExample { max_recursion } => {
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&tree.example_value(max_recursion)).unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn recurse_export(
|
||||
node: &TreeNode,
|
||||
parent_name: &str,
|
||||
out: &mut String,
|
||||
already_processed: &mut HashSet<String>,
|
||||
) {
|
||||
let key = format!("{} #> {}", parent_name, node.name);
|
||||
if already_processed.contains(&key) {
|
||||
return;
|
||||
}
|
||||
already_processed.insert(key);
|
||||
|
||||
if !parent_name.is_empty() && matches!(node.r#type, NodeType::Object { .. }) {
|
||||
writeln!(out, "\"{}\" -> \"{}\";", parent_name, node.name).unwrap();
|
||||
}
|
||||
|
||||
match &node.r#type {
|
||||
NodeType::Array { item } => {
|
||||
let mut item = item.clone();
|
||||
item.name.push_str(" []");
|
||||
recurse_export(&item, parent_name, out, already_processed);
|
||||
}
|
||||
NodeType::Object { children, .. } => {
|
||||
for child in children {
|
||||
recurse_export(&child.node, &node.name, out, already_processed);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn graphviz_export(tree: &TreeNode) -> String {
|
||||
let mut out = "digraph G {\n".to_string();
|
||||
|
||||
let mut already_processed = HashSet::new();
|
||||
|
||||
recurse_export(tree, "", &mut out, &mut already_processed);
|
||||
|
||||
out.push_str("}\n");
|
||||
out
|
||||
}
|
||||
|
||||
fn tex_escape_str(s: &str) -> String {
|
||||
s.replace('_', "\\_")
|
||||
.trim_matches('\n')
|
||||
.replace("\n\n", "\n")
|
||||
.replace('\n', "\\newline\n")
|
||||
}
|
||||
|
||||
fn tex_type_str(t: &TreeNode) -> String {
|
||||
match &t.r#type {
|
||||
NodeType::Null => "NULL".to_string(),
|
||||
NodeType::Boolean => "bool".to_string(),
|
||||
NodeType::Array { item } => format!("{}[]", tex_type_str(item)),
|
||||
NodeType::Object { .. } => t.name.to_string(),
|
||||
NodeType::String => "string".to_string(),
|
||||
NodeType::Number => "number".to_string(),
|
||||
NodeType::Integer => "integer".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn tex_export_inner(tree: &ObjectChild, out: &mut String, required: bool) {
|
||||
let type_str = tex_type_str(&tree.node);
|
||||
|
||||
writeln!(
|
||||
out,
|
||||
"\\schemaprop{{{}}}{{{}}}{{{}}}{{{}}}{{{}}}",
|
||||
tex_escape_str(&tree.name),
|
||||
match required {
|
||||
true => "true",
|
||||
false => "false",
|
||||
},
|
||||
tex_escape_str(&type_str),
|
||||
match &tree.node.description {
|
||||
None => "".to_string(),
|
||||
Some(d) => tex_escape_str(d),
|
||||
},
|
||||
match (&tree.node.r#type, tree.node.examples.get(0)) {
|
||||
(_, Some(e)) => tex_escape_str(e),
|
||||
(NodeType::Array { item }, _) if !item.examples.is_empty() => {
|
||||
format!("[{}]", &item.examples.get(0).unwrap())
|
||||
}
|
||||
_ => "".to_string(),
|
||||
}
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn tex_adapt_name(i: &str) -> String {
|
||||
i.replace('0', "zero")
|
||||
.replace('1', "one")
|
||||
.replace('2', "two")
|
||||
.replace('3', "three")
|
||||
.replace('4', "four")
|
||||
.replace('5', "five")
|
||||
.replace('6', "six")
|
||||
.replace('7', "seven")
|
||||
.replace('8', "height")
|
||||
.replace('9', "nine")
|
||||
}
|
||||
|
||||
fn tex_export(tree: &TreeNode) -> String {
|
||||
let mut out = String::new();
|
||||
writeln!(out, "% START OF EXPORT OF SCHEMA {}", tree.name).unwrap();
|
||||
|
||||
let box_name = format!("\\codeBox{}", tex_adapt_name(&tree.name));
|
||||
if matches!(tree.r#type, NodeType::Object { .. }) {
|
||||
// JSON export
|
||||
out.push_str(&format!("\\newsavebox{{{box_name}}}\n"));
|
||||
out.push_str(&format!("\\begin{{lrbox}}{{{box_name}}}\n"));
|
||||
out.push_str(&format!(
|
||||
"\\begin{{jsonsample}}{{{}}}\n",
|
||||
tex_escape_str(&tree.name)
|
||||
));
|
||||
out.push_str("\\begin{lstlisting}[language=json]\n");
|
||||
let json_doc = serde_json::to_string_pretty(&tree.example_value(1)).unwrap();
|
||||
let replace_key = serde_json::to_string(REF_OBJECT).unwrap();
|
||||
out.push_str(&json_doc.replace(&format!("{replace_key}:"), "$ref"));
|
||||
out.push_str("\n\\end{lstlisting}\n");
|
||||
out.push_str("\\end{jsonsample}\n");
|
||||
out.push_str("\\end{lrbox}\n");
|
||||
}
|
||||
|
||||
writeln!(
|
||||
out,
|
||||
"\\newcommand{{\\schemadef{}}}{{",
|
||||
tex_adapt_name(&tree.name)
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match &tree.r#type {
|
||||
NodeType::Object { children, required } => {
|
||||
writeln!(out, "\\schemaname{{{}}}", tex_escape_str(&tree.name)).unwrap();
|
||||
|
||||
if let Some(description) = &tree.description {
|
||||
writeln!(
|
||||
out,
|
||||
"\\schemadescription{{{}}}",
|
||||
tex_escape_str(description)
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
out.push_str("\\begin{schemabody}\n");
|
||||
out.push_str("\\begin{schemaprops}\n");
|
||||
for child in children {
|
||||
tex_export_inner(
|
||||
child,
|
||||
&mut out,
|
||||
required
|
||||
.as_ref()
|
||||
.map(|r| r.contains(&child.name))
|
||||
.unwrap_or(false),
|
||||
);
|
||||
}
|
||||
out.push_str("\\end{schemaprops}\n");
|
||||
|
||||
out.push_str(&format!("\\usebox{{{box_name}}}\n"));
|
||||
out.push_str("\\end{schemabody}\n");
|
||||
}
|
||||
_ => tex_export_inner(
|
||||
&ObjectChild {
|
||||
name: tree.name.to_string(),
|
||||
node: tree.clone(),
|
||||
},
|
||||
&mut out,
|
||||
false,
|
||||
),
|
||||
}
|
||||
|
||||
out.push_str("}\n");
|
||||
writeln!(out, "% END OF EXPORT OF SCHEMAS {}", tree.name).unwrap();
|
||||
out
|
||||
}
|
||||
|
||||
fn json_schema(tree: &TreeNode) -> String {
|
||||
serde_json::to_string(&tree.json_schema()).unwrap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user