Support types with const generics (#239)
Co-authored-by: Spencer Sharkey <spsharkey@tesla.com>
This commit is contained in:
parent
0303f0334e
commit
37478d764e
5 changed files with 129 additions and 21 deletions
|
@ -5,6 +5,7 @@
|
|||
### Added:
|
||||
|
||||
- Implement `JsonSchema` for `semver::Version` (https://github.com/GREsau/schemars/pull/195 / https://github.com/GREsau/schemars/pull/238)
|
||||
- Include const generics in generated schema names (https://github.com/GREsau/schemars/pull/179 / https://github.com/GREsau/schemars/pull/239)
|
||||
|
||||
### Changed:
|
||||
|
||||
|
|
14
schemars/tests/expected/schema-name-const-generics.json
Normal file
14
schemars/tests/expected/schema-name-const-generics.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "const-generics-z-42",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"foo"
|
||||
],
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
63
schemars/tests/expected/schema-name-mixed-generics.json
Normal file
63
schemars/tests/expected/schema-name-mixed-generics.json
Normal file
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "MixedGenericStruct_for_MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String_and_42_and_z",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"foo",
|
||||
"generic"
|
||||
],
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"generic": {
|
||||
"$ref": "#/definitions/MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"MySimpleStruct": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"foo"
|
||||
],
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"inner",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w"
|
||||
],
|
||||
"properties": {
|
||||
"inner": {
|
||||
"$ref": "#/definitions/MySimpleStruct"
|
||||
},
|
||||
"t": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"u": {
|
||||
"type": "null"
|
||||
},
|
||||
"v": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"w": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,3 +49,29 @@ fn overriden_with_rename_multiple_type_params() -> TestResult {
|
|||
"schema-name-custom",
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(JsonSchema)]
|
||||
#[schemars(rename = "const-generics-{BAR}-")]
|
||||
struct ConstGenericStruct<const FOO: usize, const BAR: char> {
|
||||
foo: i32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overriden_with_rename_const_generics() -> TestResult {
|
||||
test_default_generated_schema::<ConstGenericStruct<42, 'z'>>("schema-name-const-generics")
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(JsonSchema)]
|
||||
struct MixedGenericStruct<T, const FOO: usize, const BAR: char> {
|
||||
generic: T,
|
||||
foo: i32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_name_mixed_generics() -> TestResult {
|
||||
test_default_generated_schema::<MixedGenericStruct<MyStruct<i32, (), bool, Vec<String>>, 42, 'z'>>(
|
||||
"schema-name-mixed-generics",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -95,25 +95,29 @@ fn derive_json_schema(
|
|||
|
||||
// FIXME improve handling of generic type params which may not implement JsonSchema
|
||||
let type_params: Vec<_> = cont.generics.type_params().map(|ty| &ty.ident).collect();
|
||||
let schema_name =
|
||||
if type_params.is_empty() || (cont.attrs.is_renamed && !schema_base_name.contains('{')) {
|
||||
let const_params: Vec<_> = cont.generics.const_params().map(|c| &c.ident).collect();
|
||||
let params: Vec<_> = type_params.iter().chain(const_params.iter()).collect();
|
||||
|
||||
let schema_name = if params.is_empty()
|
||||
|| (cont.attrs.is_renamed && !schema_base_name.contains('{'))
|
||||
{
|
||||
quote! {
|
||||
#schema_base_name.to_owned()
|
||||
}
|
||||
} else if cont.attrs.is_renamed {
|
||||
let mut schema_name_fmt = schema_base_name;
|
||||
for tp in &type_params {
|
||||
for tp in ¶ms {
|
||||
schema_name_fmt.push_str(&format!("{{{}:.0}}", tp));
|
||||
}
|
||||
quote! {
|
||||
format!(#schema_name_fmt #(,#type_params=#type_params::schema_name())*)
|
||||
format!(#schema_name_fmt #(,#type_params=#type_params::schema_name())* #(,#const_params=#const_params)*)
|
||||
}
|
||||
} else {
|
||||
let mut schema_name_fmt = schema_base_name;
|
||||
schema_name_fmt.push_str("_for_{}");
|
||||
schema_name_fmt.push_str(&"_and_{}".repeat(type_params.len() - 1));
|
||||
schema_name_fmt.push_str(&"_and_{}".repeat(params.len() - 1));
|
||||
quote! {
|
||||
format!(#schema_name_fmt #(,#type_params::schema_name())*)
|
||||
format!(#schema_name_fmt #(,#type_params::schema_name())* #(,#const_params)*)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue