diff --git a/Cargo.lock b/Cargo.lock index 078afe0..db56f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.45" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7" +checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" [[package]] name = "autocfg" @@ -37,9 +37,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "bytes" @@ -109,9 +109,9 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ "cfg-if", ] @@ -139,6 +139,7 @@ dependencies = [ "percent-encoding", "progenitor", "reqwest", + "schemars", "serde", "uuid", ] @@ -153,6 +154,15 @@ dependencies = [ "newline-converter", ] +[[package]] +name = "fastrand" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +dependencies = [ + "instant", +] + [[package]] name = "fnv" version = "1.0.7" @@ -284,9 +294,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if", "libc", @@ -295,9 +305,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" dependencies = [ "bytes", "fnv", @@ -329,13 +339,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] @@ -357,15 +367,15 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.15" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes", "futures-channel", @@ -376,7 +386,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -411,15 +421,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown", "serde", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipnet" version = "2.3.1" @@ -432,6 +451,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "js-sys" version = "0.3.55" @@ -449,9 +474,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.107" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "log" @@ -556,15 +581,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "openapiv3" -version = "1.0.0-beta.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45518fa48878a21efa793483d3c5a3dd5f8f98026fc3dade65104d8b78bb535" +checksum = "9de1b830d6f0f82e832f5a173d54f827f233e75b30f0f787c1289cca956879f8" dependencies = [ "indexmap", "serde", @@ -587,15 +612,15 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.71" +version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ "autocfg", "cc", @@ -621,9 +646,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -633,21 +658,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" - -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -665,6 +684,7 @@ dependencies = [ "progenitor-impl", "progenitor-macro", "reqwest", + "schemars", "serde", "serde_json", "uuid", @@ -707,59 +727,21 @@ dependencies = [ "proc-macro2", "progenitor-impl", "quote", + "serde", "serde_json", + "serde_tokenstream", "syn", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" version = "0.2.10" @@ -797,15 +779,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -823,6 +806,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-util", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -843,9 +827,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -868,21 +852,23 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271ac0c667b8229adf70f0f957697c96fafd7486ab7481e15dc5e45e3e6a4368" +checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3" dependencies = [ + "chrono", "dyn-clone", "schemars_derive", "serde", "serde_json", + "uuid", ] [[package]] name = "schemars_derive" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ebda811090b257411540779860bc09bf321bc587f58d2c5864309d1566214e7" +checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b" dependencies = [ "proc-macro2", "quote", @@ -933,18 +919,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" dependencies = [ "proc-macro2", "quote", @@ -964,15 +950,26 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e277c495ac6cd1a01a58d0a0c574568b4d1ddf14f59965c6a58b8d96400b54f3" +checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] +[[package]] +name = "serde_tokenstream" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6deb15c3a535e81438110111d90168d91721652f502abb147f31cde129f683d" +dependencies = [ + "proc-macro2", + "serde", + "syn", +] + [[package]] name = "serde_urlencoded" version = "0.7.0" @@ -980,7 +977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -1003,9 +1000,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" dependencies = [ "proc-macro2", "quote", @@ -1014,13 +1011,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if", + "fastrand", "libc", - "rand", "redox_syscall", "remove_dir_all", "winapi", @@ -1073,11 +1070,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", "bytes", "libc", "memchr", @@ -1158,7 +1154,7 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typify" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#df983c2981fc055efeba3fc360e724221703d4bd" +source = "git+https://github.com/oxidecomputer/typify#a45d3058ec748c7040988700a003e4ef9aac6f02" dependencies = [ "typify-impl", "typify-macro", @@ -1167,7 +1163,7 @@ dependencies = [ [[package]] name = "typify-impl" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#df983c2981fc055efeba3fc360e724221703d4bd" +source = "git+https://github.com/oxidecomputer/typify#a45d3058ec748c7040988700a003e4ef9aac6f02" dependencies = [ "convert_case", "log", @@ -1183,12 +1179,14 @@ dependencies = [ [[package]] name = "typify-macro" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#df983c2981fc055efeba3fc360e724221703d4bd" +source = "git+https://github.com/oxidecomputer/typify#a45d3058ec748c7040988700a003e4ef9aac6f02" dependencies = [ "proc-macro2", "quote", "schemars", + "serde", "serde_json", + "serde_tokenstream", "syn", "typify-impl", ] diff --git a/Cargo.toml b/Cargo.toml index 6ce8c6a..f1d6fa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,16 @@ [workspace] members = [ + "example-build", + "example-macro", "progenitor", "progenitor-client", "progenitor-impl", "progenitor-macro", - "example-build", - "example-macro", ] default-members = [ + "example-build", + "example-macro", "progenitor", "progenitor-client", "progenitor-impl", diff --git a/example-build/Cargo.toml b/example-build/Cargo.toml index 07c06b5..86f4f41 100644 --- a/example-build/Cargo.toml +++ b/example-build/Cargo.toml @@ -6,11 +6,11 @@ edition = "2018" [dependencies] anyhow = "1.0" -percent-encoding = "2.1" -serde = { version = "1.0", features = ["derive"] } -reqwest = { version = "0.11", features = ["json", "stream"] } -uuid = { version = "0.8", features = ["serde", "v4"] } chrono = { version = "0.4", features = ["serde"] } +percent-encoding = "2.1" +reqwest = { version = "0.11", features = ["json", "stream"] } +serde = { version = "1.0", features = ["derive"] } +uuid = { version = "0.8", features = ["serde", "v4"] } [build-dependencies] progenitor = { path = "../progenitor" } diff --git a/example-macro/Cargo.toml b/example-macro/Cargo.toml index 5a8df34..6eb4e7e 100644 --- a/example-macro/Cargo.toml +++ b/example-macro/Cargo.toml @@ -5,10 +5,11 @@ authors = ["Adam H. Leventhal "] edition = "2018" [dependencies] -progenitor = { path = "../progenitor" } anyhow = "1.0" -percent-encoding = "2.1" -serde = { version = "1.0", features = ["derive"] } -reqwest = { version = "0.11", features = ["json", "stream"] } -uuid = { version = "0.8", features = ["serde", "v4"] } chrono = { version = "0.4", features = ["serde"] } +percent-encoding = "2.1" +progenitor = { path = "../progenitor" } +reqwest = { version = "0.11", features = ["json", "stream"] } +schemars = "0.8" +serde = { version = "1.0", features = ["derive"] } +uuid = { version = "0.8", features = ["serde", "v4"] } diff --git a/example-macro/src/main.rs b/example-macro/src/main.rs index 61e9b84..2120a51 100644 --- a/example-macro/src/main.rs +++ b/example-macro/src/main.rs @@ -1,16 +1,23 @@ -// Copyright 2021 Oxide Computer Company +// Copyright 2022 Oxide Computer Company use progenitor::generate_api; generate_api!( - "../sample_openapi/keeper.json", - (), - |_, request| { + spec = "../sample_openapi/keeper.json", + inner_type = (), + pre_hook = (|_, request| { println!("doing this {:?}", request); - }, - crate::all_done + }), + post_hook = crate::all_done, + derives = [schemars::JsonSchema], ); fn all_done(_: &(), _result: &reqwest::Result) {} +mod buildomat { + use progenitor::generate_api; + + generate_api!("../sample_openapi/buildomat.json"); +} + fn main() {} diff --git a/progenitor-impl/Cargo.toml b/progenitor-impl/Cargo.toml index a12fd24..a4d38b8 100644 --- a/progenitor-impl/Cargo.toml +++ b/progenitor-impl/Cargo.toml @@ -8,19 +8,19 @@ description = "An OpenAPI client generator - core implementation" [dependencies] anyhow = "1.0" +convert_case = "0.4" getopts = "0.2" indexmap = "1.7" -openapiv3 = "1.0.0-beta.5" +openapiv3 = "1.0.0" proc-macro2 = "1.0" quote = "1.0" regex = "1.5" rustfmt-wrapper = "0.1" -schemars = "0.8" +schemars = { version = "0.8", features = [ "chrono", "uuid" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" -convert_case = "0.4" -typify = { git = "https://github.com/oxidecomputer/typify" } thiserror = "1.0" +typify = { git = "https://github.com/oxidecomputer/typify" } [dev-dependencies] expectorate = "1.0" diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index cdd295b..df68840 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Oxide Computer Company +// Copyright 2022 Oxide Computer Company use std::{cmp::Ordering, collections::HashMap}; @@ -108,6 +108,11 @@ impl Generator { self } + pub fn with_derive(&mut self, derive: TokenStream) -> &mut Self { + self.type_space.add_derive(derive); + self + } + pub fn generate_tokens(&mut self, spec: &OpenAPI) -> Result { // Convert our components dictionary to schemars let schemas = spec diff --git a/progenitor-macro/Cargo.toml b/progenitor-macro/Cargo.toml index 8141a90..761db32 100644 --- a/progenitor-macro/Cargo.toml +++ b/progenitor-macro/Cargo.toml @@ -7,11 +7,13 @@ repository = "https://github.com/oxidecomputer/progenitor.git" description = "An OpenAPI client generator - macros" [dependencies] -openapiv3 = "1.0.0-beta.5" +openapiv3 = "1.0.0" +proc-macro2 = "1.0" progenitor-impl = { path = "../progenitor-impl" } quote = "1.0" -proc-macro2 = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +serde_tokenstream = "0.1.3" syn = "1.0" [lib] diff --git a/progenitor-macro/src/lib.rs b/progenitor-macro/src/lib.rs index c8ae793..099308a 100644 --- a/progenitor-macro/src/lib.rs +++ b/progenitor-macro/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Oxide Computer Company +// Copyright 2022 Oxide Computer Company use std::path::Path; @@ -6,10 +6,9 @@ use openapiv3::OpenAPI; use proc_macro::TokenStream; use progenitor_impl::Generator; use quote::{quote, ToTokens}; -use syn::{ - parse::{Parse, ParseStream}, - ExprClosure, LitStr, Token, -}; +use serde::Deserialize; +use serde_tokenstream::ParseWrapper; +use syn::LitStr; #[proc_macro] pub fn generate_api(item: TokenStream) -> TokenStream { @@ -19,101 +18,96 @@ pub fn generate_api(item: TokenStream) -> TokenStream { } } +#[derive(Deserialize)] struct Settings { - file: LitStr, - inner: Option, - pre: Option, - post: Option, + spec: ParseWrapper, + inner_type: Option>, + pre_hook: Option>, + post_hook: Option>, + #[serde(default)] + derives: Vec>, } -impl Parse for Settings { - fn parse(input: ParseStream) -> Result { - let file = input.parse::()?; - let inner = parse_inner(input)?; - let pre = parse_hook(input)?; - let post = parse_hook(input)?; +#[derive(Debug)] +struct ClosureOrPath(proc_macro2::TokenStream); - // Optional trailing comma. - if input.peek(Token!(,)) { - let _ = input.parse::(); +impl syn::parse::Parse for ClosureOrPath { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let lookahead = input.lookahead1(); + + if lookahead.peek(syn::token::Paren) { + let group: proc_macro2::Group = input.parse()?; + return syn::parse2::(group.stream()); } - Ok(Settings { - file, - inner, - pre, - post, - }) - } -} + if let Ok(closure) = input.parse::() { + return Ok(Self(closure.to_token_stream())); + } -fn parse_inner( - input: ParseStream, -) -> Result, syn::Error> { - if input.is_empty() { - return Ok(None); - } - let _: Token!(,) = input.parse()?; - if input.is_empty() { - return Ok(None); - } - Ok(Some(input.parse::()?.to_token_stream())) -} - -fn parse_hook( - input: ParseStream, -) -> Result, syn::Error> { - if input.is_empty() { - return Ok(None); - } - let _: Token!(,) = input.parse()?; - if input.is_empty() { - return Ok(None); - } - if let Ok(closure) = input.parse::() { - Ok(Some(closure.to_token_stream())) - } else { - Ok(Some(input.parse::()?.to_token_stream())) + input + .parse::() + .map(|path| Self(path.to_token_stream())) } } fn do_generate_api(item: TokenStream) -> Result { - let Settings { - file, - inner, - pre, - post, - } = syn::parse::(item)?; + let (spec, inner_type, pre_hook, post_hook, derives) = + if let Ok(spec) = syn::parse::(item.clone()) { + (spec, None, None, None, Vec::new()) + } else { + let Settings { + spec, + inner_type, + pre_hook, + post_hook, + derives, + } = serde_tokenstream::from_tokenstream(&item.into())?; + ( + spec.into_inner(), + inner_type.map(|x| x.into_inner()), + pre_hook.map(|x| x.into_inner()), + post_hook.map(|x| x.into_inner()), + derives.into_iter().map(ParseWrapper::into_inner).collect(), + ) + }; + let dir = std::env::var("CARGO_MANIFEST_DIR").map_or_else( |_| std::env::current_dir().unwrap(), |s| Path::new(&s).to_path_buf(), ); - let path = dir.join(file.value()); + let path = dir.join(spec.value()); let path_str = path.to_string_lossy(); - let spec: OpenAPI = + let oapi: OpenAPI = serde_json::from_reader(std::fs::File::open(&path).map_err(|e| { syn::Error::new( - file.span(), + spec.span(), format!("couldn't read file {}: {}", path_str, e.to_string()), ) })?) .map_err(|e| { syn::Error::new( - file.span(), + spec.span(), format!("failed to parse {}: {}", path_str, e.to_string()), ) })?; let mut builder = Generator::new(); - inner.map(|inner_type| builder.with_inner_type(inner_type)); - pre.map(|pre_hook| builder.with_pre_hook(pre_hook)); - post.map(|post_hook| builder.with_post_hook(post_hook)); - let code = builder.generate_tokens(&spec).map_err(|e| { + inner_type.map(|inner_type| { + builder.with_inner_type(inner_type.to_token_stream()) + }); + pre_hook.map(|pre_hook| builder.with_pre_hook(pre_hook.0)); + post_hook.map(|post_hook| builder.with_post_hook(post_hook.0)); + + derives.into_iter().for_each(|derive| { + builder.with_derive(derive.to_token_stream()); + }); + + let code = builder.generate_tokens(&oapi).map_err(|e| { syn::Error::new( - file.span(), - format!("generation error for {}: {}", file.value(), e.to_string()), + spec.span(), + format!("generation error for {}: {}", spec.value(), e.to_string()), ) })?; diff --git a/progenitor/Cargo.toml b/progenitor/Cargo.toml index a7490fc..97e55fc 100644 --- a/progenitor/Cargo.toml +++ b/progenitor/Cargo.toml @@ -11,7 +11,7 @@ progenitor-macro = { path = "../progenitor-macro" } progenitor-impl = { path = "../progenitor-impl" } anyhow = "1.0" getopts = "0.2" -openapiv3 = "1.0.0-beta.5" +openapiv3 = "1.0.0" serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" @@ -20,4 +20,5 @@ chrono = { version = "0.4", features = ["serde"] } futures = "0.3" percent-encoding = "2.1" reqwest = { version = "0.11", features = ["json", "stream"] } +schemars = "0.8" uuid = { version = "0.8", features = ["serde", "v4"] }