From a97d54bcaddd948d95f2142c740090ff400619fe Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Sat, 28 Dec 2019 20:11:38 +0000 Subject: [PATCH] Implement JsonSchema on smallvec + arrayvec types Documentation still needs updating. --- schemars/Cargo.toml | 12 +++++++ schemars/src/json_schema_impls/arrayvec.rs | 33 ++++++++++++++++++++ schemars/src/json_schema_impls/mod.rs | 4 +++ schemars/src/json_schema_impls/smallvec.rs | 6 ++++ schemars/tests/arrayvec.rs | 13 ++++++++ schemars/tests/expected/arrayvec.json | 10 ++++++ schemars/tests/expected/arrayvec_string.json | 5 +++ schemars/tests/expected/smallvec.json | 8 +++++ schemars/tests/smallvec.rs | 8 +++++ 9 files changed, 99 insertions(+) create mode 100644 schemars/src/json_schema_impls/arrayvec.rs create mode 100644 schemars/src/json_schema_impls/smallvec.rs create mode 100644 schemars/tests/arrayvec.rs create mode 100644 schemars/tests/expected/arrayvec.json create mode 100644 schemars/tests/expected/arrayvec_string.json create mode 100644 schemars/tests/expected/smallvec.json create mode 100644 schemars/tests/smallvec.rs diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml index 7417e8c..facdf70 100644 --- a/schemars/Cargo.toml +++ b/schemars/Cargo.toml @@ -21,6 +21,10 @@ chrono = { version = "0.4", default-features = false, optional = true } indexmap = { version = "1.2", optional = true } either = { version = "1.3", default-features = false, optional = true } uuid = { version = "0.8", default-features = false, optional = true } +smallvec = { version = "1.0", optional = true } +arrayvec = { version = "0.5", default-features = false, optional = true } +# TODO implement JsonSchema on bytes types. bytes 0.5 requires Rust 1.39+ +# bytes = { version = "0.5", default-features = false, optional = true } [dev-dependencies] pretty_assertions = "0.6.1" @@ -46,6 +50,14 @@ required-features = ["either"] name = "uuid" required-features = ["uuid"] +[[test]] +name = "smallvec" +required-features = ["smallvec"] + +[[test]] +name = "arrayvec" +required-features = ["arrayvec"] + [[test]] name = "schema_for_schema" required-features = ["impl_json_schema"] diff --git a/schemars/src/json_schema_impls/arrayvec.rs b/schemars/src/json_schema_impls/arrayvec.rs new file mode 100644 index 0000000..5e420a1 --- /dev/null +++ b/schemars/src/json_schema_impls/arrayvec.rs @@ -0,0 +1,33 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::JsonSchema; +use arrayvec::{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!(( JsonSchema for ArrayString where A: Array + Copy) => String); + +impl JsonSchema for ArrayVec +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(gen: &mut SchemaGenerator) -> Schema { + SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + items: Some(gen.subschema_for::().into()), + max_items: A::CAPACITY.try_into().ok(), + ..Default::default() + })), + ..Default::default() + } + .into() + } +} diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs index 59dd121..65fcecf 100644 --- a/schemars/src/json_schema_impls/mod.rs +++ b/schemars/src/json_schema_impls/mod.rs @@ -42,6 +42,10 @@ mod indexmap; mod either; #[cfg(feature = "uuid")] mod uuid; +#[cfg(feature = "smallvec")] +mod smallvec; +#[cfg(feature = "arrayvec")] +mod arrayvec; mod core; mod ffi; mod maps; diff --git a/schemars/src/json_schema_impls/smallvec.rs b/schemars/src/json_schema_impls/smallvec.rs new file mode 100644 index 0000000..f7a75e3 --- /dev/null +++ b/schemars/src/json_schema_impls/smallvec.rs @@ -0,0 +1,6 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::JsonSchema; +use smallvec::{Array, SmallVec}; + +forward_impl!(( JsonSchema for SmallVec where A::Item: JsonSchema) => Vec); diff --git a/schemars/tests/arrayvec.rs b/schemars/tests/arrayvec.rs new file mode 100644 index 0000000..c9903a9 --- /dev/null +++ b/schemars/tests/arrayvec.rs @@ -0,0 +1,13 @@ +mod util; +use arrayvec::{ArrayString, ArrayVec}; +use util::*; + +#[test] +fn arrayvec() -> TestResult { + test_default_generated_schema::>("arrayvec") +} + +#[test] +fn arrayvec_string() -> TestResult { + test_default_generated_schema::>("arrayvec_string") +} diff --git a/schemars/tests/expected/arrayvec.json b/schemars/tests/expected/arrayvec.json new file mode 100644 index 0000000..3de09a0 --- /dev/null +++ b/schemars/tests/expected/arrayvec.json @@ -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 +} \ No newline at end of file diff --git a/schemars/tests/expected/arrayvec_string.json b/schemars/tests/expected/arrayvec_string.json new file mode 100644 index 0000000..42f099a --- /dev/null +++ b/schemars/tests/expected/arrayvec_string.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "String", + "type": "string" +} \ No newline at end of file diff --git a/schemars/tests/expected/smallvec.json b/schemars/tests/expected/smallvec.json new file mode 100644 index 0000000..eab45c0 --- /dev/null +++ b/schemars/tests/expected/smallvec.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_String", + "type": "array", + "items": { + "type": "string" + } +} \ No newline at end of file diff --git a/schemars/tests/smallvec.rs b/schemars/tests/smallvec.rs new file mode 100644 index 0000000..bc9c6ef --- /dev/null +++ b/schemars/tests/smallvec.rs @@ -0,0 +1,8 @@ +mod util; +use smallvec::SmallVec; +use util::*; + +#[test] +fn smallvec() -> TestResult { + test_default_generated_schema::>("smallvec") +}