Repository: GREsau/schemars
Pull request #142 (2022-05-15 23:12:07)

Support uuid v1 and arrayvec 0.7
Supersedes #138

Support for the new versions of these crates is added in a backward-compatible way - the `arrayvec` and `uuid` features will still implement `JsonSchema` for types in previous versions of those crates.

The new crate versions can be used by enabling the `uuid1` and `arrayvec07` features. When I next make breaking changes to schemars, I'll probably change the `uuid` feature to behave the same as `uuid1`, since it's highly unlikely there will be a v2 of uuid according to its release notes. I will probably just remove the `arrayvec` feature, unless its maintainers announce they don't expect breaking changes.

This PR does not add any support for arrayvec 0.6, since no-one has asked for it as far as I know.

This change also updates dev dependencies and `serde_derive_internals`.

It's probably worth taking a look at the other optional dependencies, judging whether they're likely to have breaking changes in future, and if so, add version suffixes to their corresponding feature flags.

Documentation (including readme) still needs updating before merging!

GREsau: > do you think this warrants an update to the README to explain the situation?

I've documented the new flags in the README, and mentioned the deprecation of previous feature flags in the changelog, which hopefully is enough for now

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b27b983..adb9afb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
         include:
           - rust: 1.37.0
             # exclude ui_test as the output is slightly different in rustc 1.37
-            test_features: "--features impl_json_schema,chrono,indexmap,either,uuid,smallvec,arrayvec,enumset"
+            test_features: "--features impl_json_schema,chrono,indexmap,either,uuid08,smallvec,arrayvec05,enumset"
             allow_failure: false
           - rust: stable
             test_features: "--all-features"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fd40e9..7415674 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@
 ### Added:
 - Support generic default values in `default` attributes (https://github.com/GREsau/schemars/pull/83)
 - Add missing MIT licence text for usage of code from regex_syntax crate (https://github.com/GREsau/schemars/pull/132)
+- Support uuid v1 and arrayvec 0.7 via feature flags `uuid1` and `arrayvec07` (https://github.com/GREsau/schemars/pull/142)
+    - This also adds `uuid08` and `arrayvec05` feature flags for the previously supported versions of these crates. The existing `uuid` and `arrayvec` flags are still supported for backward-compatibility, but they are **deprecated**.
+    - Similarly, `indexmap1` feature flag is added, and `indexmap` flag is **deprecated**.
 
 ## [0.8.8] - 2021-11-25
 ### Added:
diff --git a/README.md b/README.md
index dbdcf8b..95940cc 100644
--- a/README.md
+++ b/README.md
@@ -264,19 +264,20 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
 - `impl_json_schema` - implements `JsonSchema` for Schemars types themselves
 - `preserve_order` - keep the order of struct fields in `Schema` and `SchemaObject`
 
-## Optional Dependencies
-Schemars can implement `JsonSchema` on types from several popular crates, enabled via optional dependencies (dependency versions are shown in brackets):
-- [`chrono`](https://crates.io/crates/chrono) (^0.4)
-- [`indexmap`](https://crates.io/crates/indexmap) (^1.2)
-- [`either`](https://crates.io/crates/either) (^1.3)
-- [`uuid`](https://crates.io/crates/uuid) (^0.8)
-- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
-- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
-- [`url`](https://crates.io/crates/url) (^2.0)
-- [`bytes`](https://crates.io/crates/bytes) (^1.0)
-- [`enumset`](https://crates.io/crates/enumset) (^1.0)
-- [`rust_decimal`](https://crates.io/crates/rust_decimal) (^1.0)
-- [`bigdecimal`](https://crates.io/crates/bigdecimal) (^0.3)
+Schemars can implement `JsonSchema` on types from several popular crates, enabled via feature flags (dependency versions are shown in brackets):
+- `chrono` - [chrono](https://crates.io/crates/chrono) (^0.4)
+- `indexmap1` - [indexmap](https://crates.io/crates/indexmap) (^1.2)
+- `either` - [either](https://crates.io/crates/either) (^1.3)
+- `uuid08` - [uuid](https://crates.io/crates/uuid) (^0.8)
+- `uuid1` - [uuid](https://crates.io/crates/uuid) (^1.0)
+- `smallvec` - [smallvec](https://crates.io/crates/smallvec) (^1.0)
+- `arrayvec05` - [arrayvec](https://crates.io/crates/arrayvec) (^0.5)
+- `arrayvec07` - [arrayvec](https://crates.io/crates/arrayvec) (^0.7)
+- `url` - [url](https://crates.io/crates/url) (^2.0)
+- `bytes` - [bytes](https://crates.io/crates/bytes) (^1.0)
+- `enumset` - [enumset](https://crates.io/crates/enumset) (^1.0)
+- `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
+- `bigdecimal` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3)
 
 For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so:
 
diff --git a/docs/4-features.md b/docs/4-features.md
index a6aee04..4f848c8 100644
--- a/docs/4-features.md
+++ b/docs/4-features.md
@@ -6,28 +6,28 @@ permalink: /features/
 ---
 
 # Feature Flags and Optional Dependencies
-
-Some functionality can be selectively enabled/disabled via [Cargo features](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section). These can be enabled when you add Schemars to your crate's cargo.toml, e.g.
-```toml
-[dependencies]
-schemars = { version = "0.6", features = ["chrono"] }
-```
-
-## Feature Flags
 - `derive` (enabled by default) - provides `#[derive(JsonSchema)]` macro
 - `impl_json_schema` - implements `JsonSchema` for Schemars types themselves
 - `preserve_order` - keep the order of struct fields in `Schema` and `SchemaObject`
 
-## Optional Dependencies
-Schemars can implement `JsonSchema` on types from several popular crates, enabled via optional dependencies (dependency versions are shown in brackets):
-- [`chrono`](https://crates.io/crates/chrono) (^0.4)
-- [`indexmap`](https://crates.io/crates/indexmap) (^1.2)
-- [`either`](https://crates.io/crates/either) (^1.3)
-- [`uuid`](https://crates.io/crates/uuid) (^0.8)
-- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
-- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
-- [`url`](https://crates.io/crates/url) (^2.0)
-- [`bytes`](https://crates.io/crates/bytes) (^1.0)
-- [`enumset`](https://crates.io/crates/enumset) (^1.0)
-- [`rust_decimal`](https://crates.io/crates/rust_decimal) (^1.0)
-- [`bigdecimal`](https://crates.io/crates/bigdecimal) (^0.3)
+Schemars can implement `JsonSchema` on types from several popular crates, enabled via feature flags (dependency versions are shown in brackets):
+- `chrono` - [chrono](https://crates.io/crates/chrono) (^0.4)
+- `indexmap1` - [indexmap](https://crates.io/crates/indexmap) (^1.2)
+- `either` - [either](https://crates.io/crates/either) (^1.3)
+- `uuid08` - [uuid](https://crates.io/crates/uuid) (^0.8)
+- `uuid1` - [uuid](https://crates.io/crates/uuid) (^1.0)
+- `smallvec` - [smallvec](https://crates.io/crates/smallvec) (^1.0)
+- `arrayvec05` - [arrayvec](https://crates.io/crates/arrayvec) (^0.5)
+- `arrayvec07` - [arrayvec](https://crates.io/crates/arrayvec) (^0.7)
+- `url` - [url](https://crates.io/crates/url) (^2.0)
+- `bytes` - [bytes](https://crates.io/crates/bytes) (^1.0)
+- `enumset` - [enumset](https://crates.io/crates/enumset) (^1.0)
+- `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
+- `bigdecimal` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3)
+
+For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so:
+
+```toml
+[dependencies]
+schemars = { version = "0.8", features = ["chrono"] }
+```
diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml
index bc1097f..3231cd8 100644
--- a/schemars/Cargo.toml
+++ b/schemars/Cargo.toml
@@ -19,11 +19,13 @@ serde_json = "1.0"
 dyn-clone = "1.0"
 
 chrono = { version = "0.4", default-features = false, optional = true }
-indexmap = { version = "1.2", features=["serde-1"], optional = true }
+indexmap = { version = "1.2", features = ["serde-1"], optional = true }
 either = { version = "1.3", default-features = false, optional = true }
-uuid = { version = "0.8", default-features = false, optional = true }
+uuid08 = { version = "0.8", default-features = false, optional = true, package = "uuid" }
+uuid1 = { version = "1.0", default-features = false, optional = true, package = "uuid" }
 smallvec = { version = "1.0", optional = true }
-arrayvec = { version = "0.5", default-features = false, optional = true }
+arrayvec05 = { version = "0.5", default-features = false, optional = true, package = "arrayvec" }
+arrayvec07 = { version = "0.7", default-features = false, optional = true, package = "arrayvec" }
 url = { version = "2.0", default-features = false, optional = true }
 bytes = { version = "1.0", optional = true }
 rust_decimal = { version = "1", default-features = false, optional = true }
@@ -31,7 +33,7 @@ bigdecimal = { version = "0.3", default-features = false, optional = true }
 enumset = { version = "1.0", optional = true }
 
 [dev-dependencies]
-pretty_assertions = "0.6.1"
+pretty_assertions = "1.2.1"
 trybuild = "1.0"
 
 [features]
@@ -48,6 +50,12 @@ impl_json_schema = ["derive"]
 # derive_json_schema will be removed in a later version
 derive_json_schema = ["impl_json_schema"]
 
+# `uuid` feature contains `uuid08` only for back-compat - will be changed to include uuid 1.0 instead in a later version
+uuid = ["uuid08"]
+# `arrayvec` feature without version suffix is included only for back-compat - will be removed in a later version
+arrayvec = ["arrayvec05"]
+indexmap1 = ["indexmap"]
+
 ui_test = []
 
 [[test]]
@@ -64,7 +72,7 @@ required-features = ["either"]
 
 [[test]]
 name = "uuid"
-required-features = ["uuid"]
+required-features = ["uuid08", "uuid1"]
 
 [[test]]
 name = "smallvec"
@@ -76,7 +84,7 @@ required-features = ["bytes"]
 
 [[test]]
 name = "arrayvec"
-required-features = ["arrayvec"]
+required-features = ["arrayvec05", "arrayvec07"]
 
 [[test]]
 name = "schema_for_schema"
diff --git a/schemars/src/json_schema_impls/arrayvec.rs b/schemars/src/json_schema_impls/arrayvec05.rs
similarity index 95%
rename from schemars/src/json_schema_impls/arrayvec.rs
rename to schemars/src/json_schema_impls/arrayvec05.rs
index 047e3d0..281bde7 100644
--- a/schemars/src/json_schema_impls/arrayvec.rs
+++ b/schemars/src/json_schema_impls/arrayvec05.rs
@@ -1,7 +1,7 @@
 use crate::gen::SchemaGenerator;
 use crate::schema::*;
 use crate::JsonSchema;
-use arrayvec::{Array, ArrayString, ArrayVec};
+use arrayvec05::{Array, ArrayString, ArrayVec};
 use std::convert::TryInto;
 
 // Do not set maxLength on the schema as that describes length in characters, but we only
diff --git a/schemars/src/json_schema_impls/arrayvec07.rs b/schemars/src/json_schema_impls/arrayvec07.rs
new file mode 100644
index 0000000..e2d92c5
--- /dev/null
+++ b/schemars/src/json_schema_impls/arrayvec07.rs
@@ -0,0 +1,33 @@
+use crate::gen::SchemaGenerator;
+use crate::schema::*;
+use crate::JsonSchema;
+use arrayvec07::{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!((<const CAP: usize> JsonSchema for ArrayString<CAP>) => String);
+
+impl<T, const CAP: usize> JsonSchema for ArrayVec<T, CAP>
+where
+    T: JsonSchema,
+{
+    no_ref_schema!();
+
+    fn schema_name() -> String {
+        format!("Array_up_to_size_{}_of_{}", CAP, T::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::<T>().into()),
+                max_items: CAP.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 950f0f7..9925442 100644
--- a/schemars/src/json_schema_impls/mod.rs
+++ b/schemars/src/json_schema_impls/mod.rs
@@ -36,8 +36,10 @@ macro_rules! forward_impl {
 }
 
 mod array;
-#[cfg(feature = "arrayvec")]
-mod arrayvec;
+#[cfg(feature = "arrayvec05")]
+mod arrayvec05;
+#[cfg(feature = "arrayvec07")]
+mod arrayvec07;
 #[cfg(std_atomic)]
 mod atomic;
 #[cfg(feature = "bytes")]
@@ -45,7 +47,7 @@ mod bytes;
 #[cfg(feature = "chrono")]
 mod chrono;
 mod core;
-#[cfg(any(feature = "rust_decimal", feature="bigdecimal"))]
+#[cfg(any(feature = "rust_decimal", feature = "bigdecimal"))]
 mod decimal;
 #[cfg(feature = "either")]
 mod either;
@@ -66,6 +68,8 @@ mod time;
 mod tuple;
 #[cfg(feature = "url")]
 mod url;
-#[cfg(feature = "uuid")]
-mod uuid;
+#[cfg(feature = "uuid08")]
+mod uuid08;
+#[cfg(feature = "uuid1")]
+mod uuid1;
 mod wrapper;
diff --git a/schemars/src/json_schema_impls/uuid08.rs b/schemars/src/json_schema_impls/uuid08.rs
new file mode 100644
index 0000000..9e6dc58
--- /dev/null
+++ b/schemars/src/json_schema_impls/uuid08.rs
@@ -0,0 +1,21 @@
+use crate::gen::SchemaGenerator;
+use crate::schema::*;
+use crate::JsonSchema;
+use uuid08::Uuid;
+
+impl JsonSchema for Uuid {
+    no_ref_schema!();
+
+    fn schema_name() -> String {
+        "Uuid".to_string()
+    }
+
+    fn json_schema(_: &mut SchemaGenerator) -> Schema {
+        SchemaObject {
+            instance_type: Some(InstanceType::String.into()),
+            format: Some("uuid".to_string()),
+            ..Default::default()
+        }
+        .into()
+    }
+}
diff --git a/schemars/src/json_schema_impls/uuid.rs b/schemars/src/json_schema_impls/uuid1.rs
similarity index 96%
rename from schemars/src/json_schema_impls/uuid.rs
rename to schemars/src/json_schema_impls/uuid1.rs
index c90a78b..85d6789 100644
--- a/schemars/src/json_schema_impls/uuid.rs
+++ b/schemars/src/json_schema_impls/uuid1.rs
@@ -1,7 +1,7 @@
 use crate::gen::SchemaGenerator;
 use crate::schema::*;
 use crate::JsonSchema;
-use uuid::Uuid;
+use uuid1::Uuid;
 
 impl JsonSchema for Uuid {
     no_ref_schema!();
diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs
index 5ef0bdf..2094c42 100644
--- a/schemars/src/lib.rs
+++ b/schemars/src/lib.rs
@@ -259,25 +259,28 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
 - `impl_json_schema` - implements `JsonSchema` for Schemars types themselves
 - `preserve_order` - keep the order of struct fields in `Schema` and `SchemaObject`
 
-## Optional Dependencies
-Schemars can implement `JsonSchema` on types from several popular crates, enabled via optional dependencies (dependency versions are shown in brackets):
-- [`chrono`](https://crates.io/crates/chrono) (^0.4)
-- [`indexmap`](https://crates.io/crates/indexmap) (^1.2)
-- [`either`](https://crates.io/crates/either) (^1.3)
-- [`uuid`](https://crates.io/crates/uuid) (^0.8)
-- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
-- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
-- [`url`](https://crates.io/crates/url) (^2.0)
-- [`bytes`](https://crates.io/crates/bytes) (^1.0)
-- [`enumset`](https://crates.io/crates/enumset) (^1.0)
-- [`rust_decimal`](https://crates.io/crates/rust_decimal) (^1.0)
-- [`bigdecimal`](https://crates.io/crates/bigdecimal) (^0.3)
+Schemars can implement `JsonSchema` on types from several popular crates, enabled via feature flags (dependency versions are shown in brackets):
+- `chrono` - [chrono](https://crates.io/crates/chrono) (^0.4)
+- `indexmap1` - [indexmap](https://crates.io/crates/indexmap) (^1.2)
+- `either` - [either](https://crates.io/crates/either) (^1.3)
+- `uuid08` - [uuid](https://crates.io/crates/uuid) (^0.8)
+- `uuid1` - [uuid](https://crates.io/crates/uuid) (^1.0)
+- `smallvec` - [smallvec](https://crates.io/crates/smallvec) (^1.0)
+- `arrayvec05` - [arrayvec](https://crates.io/crates/arrayvec) (^0.5)
+- `arrayvec07` - [arrayvec](https://crates.io/crates/arrayvec) (^0.7)
+- `url` - [url](https://crates.io/crates/url) (^2.0)
+- `bytes` - [bytes](https://crates.io/crates/bytes) (^1.0)
+- `enumset` - [enumset](https://crates.io/crates/enumset) (^1.0)
+- `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
+- `bigdecimal` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3)
 
 For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so:
 
 ```toml
 [dependencies]
 schemars = { version = "0.8", features = ["chrono"] }
+```
+
 ```
 */
 
diff --git a/schemars_derive/Cargo.toml b/schemars_derive/Cargo.toml
index 53a6408..fb058a8 100644
--- a/schemars_derive/Cargo.toml
+++ b/schemars_derive/Cargo.toml
@@ -17,7 +17,7 @@ proc-macro = true
 proc-macro2 = "1.0"
 quote = "1.0"
 syn = { version = "1.0", features = ["extra-traits"] }
-serde_derive_internals = "0.25"
+serde_derive_internals = "0.26.0"
 
 [dev-dependencies]
-pretty_assertions = "0.6.1"
+pretty_assertions = "1.2.1"


Test patch:
diff --git a/schemars/tests/arrayvec.rs b/schemars/tests/arrayvec.rs
index 62a2676..b00b395 100644
--- a/schemars/tests/arrayvec.rs
+++ b/schemars/tests/arrayvec.rs
@@ -1,13 +1,22 @@
 mod util;
-use arrayvec::{ArrayString, ArrayVec};
 use util::*;
 
 #[test]
-fn arrayvec() -> TestResult {
-    test_default_generated_schema::<ArrayVec<[i32; 16]>>("arrayvec")
+fn arrayvec05() -> TestResult {
+    test_default_generated_schema::<arrayvec05::ArrayVec<[i32; 16]>>("arrayvec")
 }
 
 #[test]
-fn arrayvec_string() -> TestResult {
-    test_default_generated_schema::<ArrayString<[u8; 16]>>("arrayvec_string")
+fn arrayvec05_string() -> TestResult {
+    test_default_generated_schema::<arrayvec05::ArrayString<[u8; 16]>>("arrayvec_string")
+}
+
+#[test]
+fn arrayvec07() -> TestResult {
+    test_default_generated_schema::<arrayvec07::ArrayVec<i32, 16>>("arrayvec")
+}
+
+#[test]
+fn arrayvec07_string() -> TestResult {
+    test_default_generated_schema::<arrayvec07::ArrayString<16>>("arrayvec_string")
 }
diff --git a/schemars/tests/util/mod.rs b/schemars/tests/util/mod.rs
index e83671f..595d68b 100644
--- a/schemars/tests/util/mod.rs
+++ b/schemars/tests/util/mod.rs
@@ -2,7 +2,6 @@ use pretty_assertions::assert_eq;
 use schemars::{gen::SchemaSettings, schema::RootSchema, schema_for, JsonSchema};
 use std::error::Error;
 use std::fs;
-use std::panic;
 
 pub type TestResult = Result<(), Box<dyn Error>>;
 
diff --git a/schemars/tests/uuid.rs b/schemars/tests/uuid.rs
index 250e2a3..bd673b5 100644
--- a/schemars/tests/uuid.rs
+++ b/schemars/tests/uuid.rs
@@ -1,8 +1,12 @@
 mod util;
 use util::*;
-use uuid::Uuid;
 
 #[test]
-fn uuid() -> TestResult {
-    test_default_generated_schema::<Uuid>("uuid")
+fn uuid08() -> TestResult {
+    test_default_generated_schema::<uuid08::Uuid>("uuid")
+}
+
+#[test]
+fn uuid1() -> TestResult {
+    test_default_generated_schema::<uuid1::Uuid>("uuid")
 }