diff --git a/Cargo.lock b/Cargo.lock index fc73316..7b3de8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" [[package]] name = "async-stream" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" dependencies = [ "async-stream-impl", "futures-core", @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ "proc-macro2", "quote", @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ "proc-macro2", "quote", @@ -243,7 +243,7 @@ dependencies = [ [[package]] name = "dropshot" version = "0.6.1-dev" -source = "git+https://github.com/oxidecomputer/dropshot#18078c4909d6260dddb924915f830de12840871d" +source = "git+https://github.com/oxidecomputer/dropshot#0b259fb094361e0a626e0f4d16d8a7c715554f97" dependencies = [ "async-stream", "async-trait", @@ -276,12 +276,13 @@ dependencies = [ "toml", "usdt", "uuid 0.8.2", + "version_check", ] [[package]] name = "dropshot_endpoint" version = "0.6.1-dev" -source = "git+https://github.com/oxidecomputer/dropshot#18078c4909d6260dddb924915f830de12840871d" +source = "git+https://github.com/oxidecomputer/dropshot#0b259fb094361e0a626e0f4d16d8a7c715554f97" dependencies = [ "proc-macro2", "quote", @@ -584,9 +585,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", @@ -666,9 +667,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -939,9 +940,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "percent-encoding" @@ -1012,9 +1013,9 @@ checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] @@ -1221,9 +1222,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "0.3.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ "base64", ] @@ -1344,18 +1345,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1472,9 +1473,9 @@ dependencies = [ [[package]] name = "slog-json" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f825ce7346f40aa318111df5d3a94945a7fdca9081584cb9b05692fb3dfcb4" +checksum = "3e1e53f61af1e3c8b852eef0a9dee29008f55d6dd63794f3f12cef786cf0f219" dependencies = [ "serde", "serde_json", @@ -1707,9 +1708,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls", "tokio", @@ -1732,9 +1733,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] @@ -1793,7 +1794,7 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "typify" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#4494446aac57ad0841f0d91ba0a9c1acca5de228" +source = "git+https://github.com/oxidecomputer/typify#90894d81e303cd56056b179f31b60401efa3462d" dependencies = [ "typify-impl", "typify-macro", @@ -1802,7 +1803,7 @@ dependencies = [ [[package]] name = "typify-impl" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#4494446aac57ad0841f0d91ba0a9c1acca5de228" +source = "git+https://github.com/oxidecomputer/typify#90894d81e303cd56056b179f31b60401efa3462d" dependencies = [ "heck", "log", @@ -1819,7 +1820,7 @@ dependencies = [ [[package]] name = "typify-macro" version = "0.0.6-dev" -source = "git+https://github.com/oxidecomputer/typify#4494446aac57ad0841f0d91ba0a9c1acca5de228" +source = "git+https://github.com/oxidecomputer/typify#90894d81e303cd56056b179f31b60401efa3462d" dependencies = [ "proc-macro2", "quote", @@ -1884,9 +1885,9 @@ dependencies = [ [[package]] name = "usdt" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3877c300bc107d8d05455e8e2bec271ca9e1d24fbc17e3ef27d18b9b53c684e2" +checksum = "5409e16f35fdba646ff4290e6f96f0bb958b43e0bd09d790c3714456a76c11ac" dependencies = [ "dof", "serde", @@ -1897,9 +1898,9 @@ dependencies = [ [[package]] name = "usdt-attr-macro" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dedf62a6eab9c6da23fa64353382ef2b73dce8891eadda8755bfed179cb2103d" +checksum = "d203cad87b8424e1fbd0fef29b6df2113e68be5dd75f4043427eb0ce6601041f" dependencies = [ "dtrace-parser", "proc-macro2", @@ -1911,9 +1912,9 @@ dependencies = [ [[package]] name = "usdt-impl" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dda9311a9f1452ebc752d264e9d1e3c2dac9807219e19471bcef3bd1b7f90cb" +checksum = "3c146394183fcea90d93e2d4602e1a7eb6cab8e807b58f99d4f343720d4e9d69" dependencies = [ "byteorder", "dof", @@ -1926,13 +1927,14 @@ dependencies = [ "syn", "thiserror", "thread-id", + "version_check", ] [[package]] name = "usdt-macro" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64160eb8f7ee61fcaef542b2f75fa807e8c3ed4b4f075e6ca0b17ea6fcea6f8" +checksum = "8dddab3586eaf539e2daddc425261daef6a6d2f85131bac7345caa8e6a423b27" dependencies = [ "dtrace-parser", "proc-macro2", @@ -1968,6 +1970,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "walkdir" version = "2.3.2" diff --git a/progenitor-impl/Cargo.toml b/progenitor-impl/Cargo.toml index 60c1d91..0db2f7a 100644 --- a/progenitor-impl/Cargo.toml +++ b/progenitor-impl/Cargo.toml @@ -9,7 +9,7 @@ description = "An OpenAPI client generator - core implementation" [dependencies] heck = "0.4.0" getopts = "0.2" -indexmap = "1.7" +indexmap = "1.8" openapiv3 = "1.0.0" proc-macro2 = "1.0" quote = "1.0" diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index 51ba51c..7550e17 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -112,6 +112,7 @@ impl Generator { .collect::>(); types.sort_by(|(a_name, _), (b_name, _)| a_name.cmp(b_name)); let types = types.into_iter().map(|(_, def)| def); + let shared = self.type_space.common_code(); let inner_property = self.inner_type.as_ref().map(|inner| { quote! { @@ -131,6 +132,7 @@ impl Generator { pub mod types { use serde::{Deserialize, Serialize}; + #shared #(#types)* } diff --git a/progenitor-impl/tests/output/test_default_params.out b/progenitor-impl/tests/output/test_default_params.out new file mode 100644 index 0000000..ec284f9 --- /dev/null +++ b/progenitor-impl/tests/output/test_default_params.out @@ -0,0 +1,79 @@ +pub use progenitor_client::{ByteStream, Error, ResponseValue}; +pub mod types { + use serde::{Deserialize, Serialize}; + mod defaults { + pub(super) fn default_u64() -> T + where + T: std::convert::TryFrom, + >::Error: std::fmt::Debug, + { + T::try_from(V).unwrap() + } + } + + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct BodyWithDefaults { + #[serde(rename = "forty-two", default = "defaults::default_u64::")] + pub forty_two: u32, + pub s: String, + #[serde(default)] + pub yes: bool, + } + + #[doc = "Error information from a response."] + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct Error { + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error_code: Option, + pub message: String, + pub request_id: String, + } +} + +#[derive(Clone)] +pub struct Client { + baseurl: String, + client: reqwest::Client, +} + +impl Client { + pub fn new(baseurl: &str) -> Self { + let dur = std::time::Duration::from_secs(15); + let client = reqwest::ClientBuilder::new() + .connect_timeout(dur) + .timeout(dur) + .build() + .unwrap(); + Self::new_with_client(baseurl, client) + } + + pub fn new_with_client(baseurl: &str, client: reqwest::Client) -> Self { + Self { + baseurl: baseurl.to_string(), + client, + } + } + + pub fn baseurl(&self) -> &String { + &self.baseurl + } + + pub fn client(&self) -> &reqwest::Client { + &self.client + } + + #[doc = "Sends a `POST` request to ``"] + pub async fn default_params<'a>( + &'a self, + body: &'a types::BodyWithDefaults, + ) -> Result, Error> { + let url = format!("{}", self.baseurl,); + let request = self.client.post(url).json(body).build()?; + let result = self.client.execute(request).await; + let response = result?; + match response.status().as_u16() { + 200..=299 => Ok(ResponseValue::stream(response)), + _ => Err(Error::ErrorResponse(ResponseValue::stream(response))), + } + } +} diff --git a/progenitor-impl/tests/test_specific.rs b/progenitor-impl/tests/test_specific.rs index 8a6ef67..e021900 100644 --- a/progenitor-impl/tests/test_specific.rs +++ b/progenitor-impl/tests/test_specific.rs @@ -4,7 +4,7 @@ use std::{str::from_utf8, sync::Arc}; use dropshot::{ endpoint, ApiDescription, HttpError, HttpResponseUpdatedNoContent, Path, - Query, RequestContext, + Query, RequestContext, TypedBody, }; use http::Response; use hyper::Body; @@ -104,3 +104,51 @@ fn test_freeform_response() { &output, ) } + +#[derive(Deserialize, JsonSchema)] +#[allow(dead_code)] +struct BodyWithDefaults { + s: String, + #[serde(default)] + yes: bool, + #[serde(default = "forty_two", rename = "forty-two")] + forty_two: u32, +} + +fn forty_two() -> u32 { + 42 +} + +#[endpoint { + method = POST, + path = "/", +}] +async fn default_params( + _rqctx: Arc>, + _body: TypedBody, +) -> Result, HttpError> { + unreachable!(); +} + +/// Test default type values. +#[test] +fn test_default_params() { + let mut api = ApiDescription::new(); + api.register(default_params).unwrap(); + + let mut out = Vec::new(); + + api.openapi("pagination-demo", "9000") + .write(&mut out) + .unwrap(); + + let out = from_utf8(&out).unwrap(); + let spec = serde_json::from_str::(out).unwrap(); + + let mut generator = Generator::new(); + let output = generator.generate_text(&spec).unwrap(); + expectorate::assert_contents( + format!("tests/output/{}.out", "test_default_params"), + &output, + ) +}