From 5553600d66daf23a069ffbbe958c02f78c05c67d Mon Sep 17 00:00:00 2001 From: Dmitry Dygalo Date: Sun, 15 Jan 2023 11:06:37 +0100 Subject: [PATCH] chore(rust): Replace `lazy_static` with `once_cell` --- CHANGELOG.md | 1 + bindings/python/Cargo.lock | 2 +- jsonschema/Cargo.toml | 3 +- jsonschema/src/compilation/mod.rs | 6 +- jsonschema/src/compilation/options.rs | 437 +++++++++++++++----------- jsonschema/src/content_encoding.rs | 16 +- jsonschema/src/content_media_type.rs | 15 +- jsonschema/src/keywords/format.rs | 36 ++- jsonschema/src/keywords/pattern.rs | 8 +- 9 files changed, 293 insertions(+), 231 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eeff13..98f4242 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Bump `base64` to `0.21`. - Bump `fancy-regex` to `0.11`. - Bump `fraction` to `0.13`. +- Replace `lazy_static` with `once_cell`. ## [0.16.1] - 2022-10-20 diff --git a/bindings/python/Cargo.lock b/bindings/python/Cargo.lock index 9205e30..0ba5a8d 100644 --- a/bindings/python/Cargo.lock +++ b/bindings/python/Cargo.lock @@ -492,9 +492,9 @@ dependencies = [ "getrandom", "iso8601", "itoa", - "lazy_static", "memchr", "num-cmp", + "once_cell", "parking_lot", "percent-encoding", "regex", diff --git a/jsonschema/Cargo.toml b/jsonschema/Cargo.toml index 0ceeb10..7ac22b0 100644 --- a/jsonschema/Cargo.toml +++ b/jsonschema/Cargo.toml @@ -34,9 +34,9 @@ fancy-regex = "0.11" fraction = { version = "0.13", default-features = false, features = ["with-bigint"] } iso8601 = "0.5" itoa = "1" -lazy_static = "1.4" memchr = "2.5" num-cmp = "0.1" +once_cell = "1.17" parking_lot = "0.12" percent-encoding = "2.1" regex = "1.6" @@ -53,6 +53,7 @@ getrandom = { version = "0.2", features = ["js"] } [dev-dependencies] bench_helpers = { path = "../bench_helpers" } criterion = { version = "0.4.0", features = [], default-features = false } +lazy_static = "1.4" # Needed for json schema test suite json_schema_test_suite = { version = "0.3.0", path = "../jsonschema-test-suite" } jsonschema-valid = "0.5" mockito = "0.31" diff --git a/jsonschema/src/compilation/mod.rs b/jsonschema/src/compilation/mod.rs index c078b32..b4a2d83 100644 --- a/jsonschema/src/compilation/mod.rs +++ b/jsonschema/src/compilation/mod.rs @@ -16,6 +16,7 @@ use crate::{ }; use ahash::AHashMap; use context::CompilationContext; +use once_cell::sync::Lazy; use options::CompilationOptions; use serde_json::Value; use std::sync::Arc; @@ -30,9 +31,8 @@ pub struct JSONSchema { config: Arc, } -lazy_static::lazy_static! { - pub static ref DEFAULT_SCOPE: Url = url::Url::parse(DEFAULT_ROOT_URL).expect("Is a valid URL"); -} +pub(crate) static DEFAULT_SCOPE: Lazy = + Lazy::new(|| url::Url::parse(DEFAULT_ROOT_URL).expect("Is a valid URL")); impl JSONSchema { /// Return a default `CompilationOptions` that can configure diff --git a/jsonschema/src/compilation/options.rs b/jsonschema/src/compilation/options.rs index 6690f9d..0edb0e8 100644 --- a/jsonschema/src/compilation/options.rs +++ b/jsonschema/src/compilation/options.rs @@ -9,203 +9,256 @@ use crate::{ schemas, ValidationError, }; use ahash::AHashMap; +use once_cell::sync::Lazy; use std::{fmt, sync::Arc}; -const EXPECT_MESSAGE: &str = "Valid meta-schema!"; - -lazy_static::lazy_static! { - static ref DRAFT4:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft4.json")).expect("Valid schema!"); - static ref DRAFT6:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft6.json")).expect("Valid schema!"); - static ref DRAFT7:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft7.json")).expect("Valid schema!"); - static ref DRAFT201909:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/schema.json")).expect("Valid schema!"); - static ref DRAFT201909_APPLICATOR:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/applicator.json")).expect("Valid schema!"); - static ref DRAFT201909_CONTENT:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/content.json")).expect("Valid schema!"); - static ref DRAFT201909_CORE:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/core.json")).expect("Valid schema!"); - static ref DRAFT201909_FORMAT:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/format.json")).expect("Valid schema!"); - static ref DRAFT201909_META_DATA:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/meta-data.json")).expect("Valid schema!"); - static ref DRAFT201909_VALIDATION:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2019-09/meta/validation.json")).expect("Valid schema!"); - static ref DRAFT202012:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/schema.json")).expect("Valid schema!"); - static ref DRAFT202012_CORE:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/core.json")).expect("Valid schema!"); - static ref DRAFT202012_APPLICATOR:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/applicator.json")).expect("Valid schema!"); - static ref DRAFT202012_UNEVALUATED:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/unevaluated.json")).expect("Valid schema!"); - static ref DRAFT202012_VALIDATION:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/validation.json")).expect("Valid schema!"); - static ref DRAFT202012_META_DATA:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/meta-data.json")).expect("Valid schema!"); - static ref DRAFT202012_FORMAT_ANNOTATION:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/format-annotation.json")).expect("Valid schema!"); - static ref DRAFT202012_CONTENT:serde_json::Value = serde_json::from_str(include_str!("../../meta_schemas/draft2020-12/meta/content.json")).expect("Valid schema!"); - - static ref META_SCHEMAS: AHashMap> = { - let mut store = AHashMap::with_capacity(3); - store.insert( - "http://json-schema.org/draft-04/schema".to_string(), - Arc::new(DRAFT4.clone()) - ); - store.insert( - "http://json-schema.org/draft-06/schema".to_string(), - Arc::new(DRAFT6.clone()) - ); - store.insert( - "http://json-schema.org/draft-07/schema".to_string(), - Arc::new(DRAFT7.clone()) - ); - #[cfg(feature = "draft201909")] - { - store.insert( - "https://json-schema.org/draft/2019-09/schema".to_string(), - Arc::new(DRAFT201909.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/applicator".to_string(), - Arc::new(DRAFT201909_APPLICATOR.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/content".to_string(), - Arc::new(DRAFT201909_CONTENT.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/core".to_string(), - Arc::new(DRAFT201909_CORE.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/format".to_string(), - Arc::new(DRAFT201909_FORMAT.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/meta-data".to_string(), - Arc::new(DRAFT201909_META_DATA.clone()) - ); - store.insert( - "https://json-schema.org/draft/2019-09/meta/validation".to_string(), - Arc::new(DRAFT201909_VALIDATION.clone()) - ); - } - #[cfg(feature = "draft202012")] - { - store.insert( - "https://json-schema.org/draft/2020-12/schema".to_string(), - Arc::new(DRAFT202012.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/core".to_string(), - Arc::new(DRAFT202012_CORE.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), - Arc::new(DRAFT202012_APPLICATOR.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/unevaluated".to_string(), - Arc::new(DRAFT202012_UNEVALUATED.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/validation".to_string(), - Arc::new(DRAFT202012_VALIDATION.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/meta-data".to_string(), - Arc::new(DRAFT202012_META_DATA.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/format-annotation".to_string(), - Arc::new(DRAFT202012_FORMAT_ANNOTATION.clone()) - ); - store.insert( - "https://json-schema.org/draft/2020-12/meta/content".to_string(), - Arc::new(DRAFT202012_CONTENT.clone()) - ); - } - store - }; - - static ref META_SCHEMA_VALIDATORS: AHashMap = { - let mut store = AHashMap::with_capacity(3); - store.insert( - schemas::Draft::Draft4, - JSONSchema::options().without_schema_validation().compile(&DRAFT4).expect(EXPECT_MESSAGE) - ); - store.insert( - schemas::Draft::Draft6, - JSONSchema::options().without_schema_validation().compile(&DRAFT6).expect(EXPECT_MESSAGE) - ); - store.insert( - schemas::Draft::Draft7, - JSONSchema::options().without_schema_validation().compile(&DRAFT7).expect(EXPECT_MESSAGE) - ); - #[cfg(feature = "draft201909")] - store.insert( - schemas::Draft::Draft201909, - JSONSchema::options() - .without_schema_validation() - .with_document( - "https://json-schema.org/draft/2019-09/meta/applicator".to_string(), - DRAFT201909_APPLICATOR.clone() - ) - .with_document( - "https://json-schema.org/draft/2019-09/meta/content".to_string(), - DRAFT201909_CONTENT.clone() - ) - .with_document( - "https://json-schema.org/draft/2019-09/meta/core".to_string(), - DRAFT201909_CORE.clone() - ) - .with_document( - "https://json-schema.org/draft/2019-09/meta/format".to_string(), - DRAFT201909_FORMAT.clone() - ) - .with_document( - "https://json-schema.org/draft/2019-09/meta/meta-data".to_string(), - DRAFT201909_META_DATA.clone() - ) - .with_document( - "https://json-schema.org/draft/2019-09/meta/validation".to_string(), - DRAFT201909_VALIDATION.clone() - ) - .compile(&DRAFT201909) - .expect(EXPECT_MESSAGE) - ); - #[cfg(feature = "draft202012")] - store.insert( - schemas::Draft::Draft202012, - JSONSchema::options() - .without_schema_validation() - .with_document( - "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), - DRAFT202012_APPLICATOR.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/core".to_string(), - DRAFT202012_CORE.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), - DRAFT202012_APPLICATOR.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/unevaluated".to_string(), - DRAFT202012_UNEVALUATED.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/validation".to_string(), - DRAFT202012_VALIDATION.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/meta-data".to_string(), - DRAFT202012_META_DATA.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/format-annotation".to_string(), - DRAFT202012_FORMAT_ANNOTATION.clone() - ) - .with_document( - "https://json-schema.org/draft/2020-12/meta/content".to_string(), - DRAFT202012_CONTENT.clone() - ) - .compile(&DRAFT202012) - .expect(EXPECT_MESSAGE) - ); - store +macro_rules! schema { + ($name:ident, $path:expr) => { + static $name: Lazy = + Lazy::new(|| serde_json::from_str(include_str!($path)).expect("Invalid schema")); }; } +schema!(DRAFT4, "../../meta_schemas/draft4.json"); +schema!(DRAFT6, "../../meta_schemas/draft6.json"); +schema!(DRAFT7, "../../meta_schemas/draft7.json"); +schema!(DRAFT201909, "../../meta_schemas/draft2019-09/schema.json"); +schema!( + DRAFT201909_APPLICATOR, + "../../meta_schemas/draft2019-09/meta/applicator.json" +); +schema!( + DRAFT201909_CONTENT, + "../../meta_schemas/draft2019-09/meta/content.json" +); +schema!( + DRAFT201909_CORE, + "../../meta_schemas/draft2019-09/meta/core.json" +); +schema!( + DRAFT201909_FORMAT, + "../../meta_schemas/draft2019-09/meta/format.json" +); +schema!( + DRAFT201909_META_DATA, + "../../meta_schemas/draft2019-09/meta/meta-data.json" +); +schema!( + DRAFT201909_VALIDATION, + "../../meta_schemas/draft2019-09/meta/validation.json" +); +schema!(DRAFT202012, "../../meta_schemas/draft2020-12/schema.json"); +schema!( + DRAFT202012_CORE, + "../../meta_schemas/draft2020-12/meta/core.json" +); +schema!( + DRAFT202012_APPLICATOR, + "../../meta_schemas/draft2020-12/meta/applicator.json" +); +schema!( + DRAFT202012_UNEVALUATED, + "../../meta_schemas/draft2020-12/meta/unevaluated.json" +); +schema!( + DRAFT202012_VALIDATION, + "../../meta_schemas/draft2020-12/meta/validation.json" +); +schema!( + DRAFT202012_META_DATA, + "../../meta_schemas/draft2020-12/meta/meta-data.json" +); +schema!( + DRAFT202012_FORMAT_ANNOTATION, + "../../meta_schemas/draft2020-12/meta/format-annotation.json" +); +schema!( + DRAFT202012_CONTENT, + "../../meta_schemas/draft2020-12/meta/content.json" +); + +static META_SCHEMAS: Lazy>> = Lazy::new(|| { + let mut store = AHashMap::with_capacity(3); + store.insert( + "http://json-schema.org/draft-04/schema".to_string(), + Arc::new(DRAFT4.clone()), + ); + store.insert( + "http://json-schema.org/draft-06/schema".to_string(), + Arc::new(DRAFT6.clone()), + ); + store.insert( + "http://json-schema.org/draft-07/schema".to_string(), + Arc::new(DRAFT7.clone()), + ); + #[cfg(feature = "draft201909")] + { + store.insert( + "https://json-schema.org/draft/2019-09/schema".to_string(), + Arc::new(DRAFT201909.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/applicator".to_string(), + Arc::new(DRAFT201909_APPLICATOR.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/content".to_string(), + Arc::new(DRAFT201909_CONTENT.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/core".to_string(), + Arc::new(DRAFT201909_CORE.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/format".to_string(), + Arc::new(DRAFT201909_FORMAT.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/meta-data".to_string(), + Arc::new(DRAFT201909_META_DATA.clone()), + ); + store.insert( + "https://json-schema.org/draft/2019-09/meta/validation".to_string(), + Arc::new(DRAFT201909_VALIDATION.clone()), + ); + } + #[cfg(feature = "draft202012")] + { + store.insert( + "https://json-schema.org/draft/2020-12/schema".to_string(), + Arc::new(DRAFT202012.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/core".to_string(), + Arc::new(DRAFT202012_CORE.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), + Arc::new(DRAFT202012_APPLICATOR.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/unevaluated".to_string(), + Arc::new(DRAFT202012_UNEVALUATED.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/validation".to_string(), + Arc::new(DRAFT202012_VALIDATION.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/meta-data".to_string(), + Arc::new(DRAFT202012_META_DATA.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/format-annotation".to_string(), + Arc::new(DRAFT202012_FORMAT_ANNOTATION.clone()), + ); + store.insert( + "https://json-schema.org/draft/2020-12/meta/content".to_string(), + Arc::new(DRAFT202012_CONTENT.clone()), + ); + } + store +}); + +const EXPECT_MESSAGE: &str = "Invalid meta-schema"; +static META_SCHEMA_VALIDATORS: Lazy> = Lazy::new(|| { + let mut store = AHashMap::with_capacity(3); + store.insert( + schemas::Draft::Draft4, + JSONSchema::options() + .without_schema_validation() + .compile(&DRAFT4) + .expect(EXPECT_MESSAGE), + ); + store.insert( + schemas::Draft::Draft6, + JSONSchema::options() + .without_schema_validation() + .compile(&DRAFT6) + .expect(EXPECT_MESSAGE), + ); + store.insert( + schemas::Draft::Draft7, + JSONSchema::options() + .without_schema_validation() + .compile(&DRAFT7) + .expect(EXPECT_MESSAGE), + ); + #[cfg(feature = "draft201909")] + store.insert( + schemas::Draft::Draft201909, + JSONSchema::options() + .without_schema_validation() + .with_document( + "https://json-schema.org/draft/2019-09/meta/applicator".to_string(), + DRAFT201909_APPLICATOR.clone(), + ) + .with_document( + "https://json-schema.org/draft/2019-09/meta/content".to_string(), + DRAFT201909_CONTENT.clone(), + ) + .with_document( + "https://json-schema.org/draft/2019-09/meta/core".to_string(), + DRAFT201909_CORE.clone(), + ) + .with_document( + "https://json-schema.org/draft/2019-09/meta/format".to_string(), + DRAFT201909_FORMAT.clone(), + ) + .with_document( + "https://json-schema.org/draft/2019-09/meta/meta-data".to_string(), + DRAFT201909_META_DATA.clone(), + ) + .with_document( + "https://json-schema.org/draft/2019-09/meta/validation".to_string(), + DRAFT201909_VALIDATION.clone(), + ) + .compile(&DRAFT201909) + .expect(EXPECT_MESSAGE), + ); + #[cfg(feature = "draft202012")] + store.insert( + schemas::Draft::Draft202012, + JSONSchema::options() + .without_schema_validation() + .with_document( + "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), + DRAFT202012_APPLICATOR.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/core".to_string(), + DRAFT202012_CORE.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/applicator".to_string(), + DRAFT202012_APPLICATOR.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/unevaluated".to_string(), + DRAFT202012_UNEVALUATED.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/validation".to_string(), + DRAFT202012_VALIDATION.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/meta-data".to_string(), + DRAFT202012_META_DATA.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/format-annotation".to_string(), + DRAFT202012_FORMAT_ANNOTATION.clone(), + ) + .with_document( + "https://json-schema.org/draft/2020-12/meta/content".to_string(), + DRAFT202012_CONTENT.clone(), + ) + .compile(&DRAFT202012) + .expect(EXPECT_MESSAGE), + ); + store +}); + /// Full configuration to guide the `JSONSchema` compilation. /// /// Using a `CompilationOptions` instance you can configure the supported draft, diff --git a/jsonschema/src/content_encoding.rs b/jsonschema/src/content_encoding.rs index 20892b1..cf4f268 100644 --- a/jsonschema/src/content_encoding.rs +++ b/jsonschema/src/content_encoding.rs @@ -1,6 +1,7 @@ use crate::error::ValidationError; use ahash::AHashMap; use base64::{engine::general_purpose, Engine as _}; +use once_cell::sync::Lazy; pub(crate) type ContentEncodingCheckType = fn(&str) -> bool; pub(crate) type ContentEncodingConverterType = @@ -19,10 +20,11 @@ pub(crate) fn from_base64( } } -lazy_static::lazy_static! { - pub(crate) static ref DEFAULT_CONTENT_ENCODING_CHECKS_AND_CONVERTERS: AHashMap<&'static str, (ContentEncodingCheckType, ContentEncodingConverterType)> = { - let mut map: AHashMap<&'static str, (ContentEncodingCheckType, ContentEncodingConverterType)> = AHashMap::with_capacity(1); - map.insert("base64", (is_base64, from_base64)); - map - }; -} +pub(crate) static DEFAULT_CONTENT_ENCODING_CHECKS_AND_CONVERTERS: Lazy< + AHashMap<&'static str, (ContentEncodingCheckType, ContentEncodingConverterType)>, +> = Lazy::new(|| { + let mut map: AHashMap<&'static str, (ContentEncodingCheckType, ContentEncodingConverterType)> = + AHashMap::with_capacity(1); + map.insert("base64", (is_base64, from_base64)); + map +}); diff --git a/jsonschema/src/content_media_type.rs b/jsonschema/src/content_media_type.rs index d01c686..22e07ba 100644 --- a/jsonschema/src/content_media_type.rs +++ b/jsonschema/src/content_media_type.rs @@ -1,4 +1,5 @@ use ahash::AHashMap; +use once_cell::sync::Lazy; use serde_json::{from_str, Value}; pub(crate) type ContentMediaTypeCheckType = fn(&str) -> bool; @@ -7,10 +8,10 @@ pub(crate) fn is_json(instance_string: &str) -> bool { from_str::(instance_string).is_ok() } -lazy_static::lazy_static! { - pub(crate) static ref DEFAULT_CONTENT_MEDIA_TYPE_CHECKS: AHashMap<&'static str, ContentMediaTypeCheckType> = { - let mut map: AHashMap<&'static str, ContentMediaTypeCheckType> = AHashMap::with_capacity(1); - map.insert("application/json", is_json); - map - }; -} +pub(crate) static DEFAULT_CONTENT_MEDIA_TYPE_CHECKS: Lazy< + AHashMap<&'static str, ContentMediaTypeCheckType>, +> = Lazy::new(|| { + let mut map: AHashMap<&'static str, ContentMediaTypeCheckType> = AHashMap::with_capacity(1); + map.insert("application/json", is_json); + map +}); diff --git a/jsonschema/src/keywords/format.rs b/jsonschema/src/keywords/format.rs index 9435278..fc4ac4c 100644 --- a/jsonschema/src/keywords/format.rs +++ b/jsonschema/src/keywords/format.rs @@ -2,6 +2,7 @@ use std::{net::IpAddr, str::FromStr}; use fancy_regex::Regex; +use once_cell::sync::Lazy; use serde_json::{Map, Value}; use url::Url; use uuid::Uuid; @@ -16,25 +17,28 @@ use crate::{ Draft, }; -lazy_static::lazy_static! { - static ref DATE_RE: Regex = - Regex::new(r"^[0-9]{4}-[0-9]{2}-[0-9]{2}\z").expect("Is a valid regex"); - static ref IRI_REFERENCE_RE: Regex = - Regex::new(r"^(\w+:(/?/?))?[^#\\\s]*(#[^\\\s]*)?\z").expect("Is a valid regex"); - static ref JSON_POINTER_RE: Regex = Regex::new(r"^(/(([^/~])|(~[01]))*)*\z").expect("Is a valid regex"); - static ref RELATIVE_JSON_POINTER_RE: Regex = - Regex::new(r"^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)\z").expect("Is a valid regex"); - static ref TIME_RE: Regex = - Regex::new( +static DATE_RE: Lazy = + Lazy::new(|| Regex::new(r"^[0-9]{4}-[0-9]{2}-[0-9]{2}\z").expect("Is a valid regex")); +static IRI_REFERENCE_RE: Lazy = + Lazy::new(|| Regex::new(r"^(\w+:(/?/?))?[^#\\\s]*(#[^\\\s]*)?\z").expect("Is a valid regex")); +static JSON_POINTER_RE: Lazy = + Lazy::new(|| Regex::new(r"^(/(([^/~])|(~[01]))*)*\z").expect("Is a valid regex")); +static RELATIVE_JSON_POINTER_RE: Lazy = Lazy::new(|| { + Regex::new(r"^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)\z").expect("Is a valid regex") +}); +static TIME_RE: Lazy = Lazy::new(|| { + Regex::new( r"^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\.[0-9]{6})?(([Zz])|([+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))\z", - ).expect("Is a valid regex"); - static ref URI_REFERENCE_RE: Regex = - Regex::new(r"^(\w+:(/?/?))?[^#\\\s]*(#[^\\\s]*)?\z").expect("Is a valid regex"); - static ref URI_TEMPLATE_RE: Regex = Regex::new( + ).expect("Is a valid regex") +}); +static URI_REFERENCE_RE: Lazy = + Lazy::new(|| Regex::new(r"^(\w+:(/?/?))?[^#\\\s]*(#[^\\\s]*)?\z").expect("Is a valid regex")); +static URI_TEMPLATE_RE: Lazy = Lazy::new(|| { + Regex::new( r#"^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*})*\z"# ) - .expect("Is a valid regex"); -} + .expect("Is a valid regex") +}); macro_rules! format_validator { ($validator:ident, $format_name:tt) => { diff --git a/jsonschema/src/keywords/pattern.rs b/jsonschema/src/keywords/pattern.rs index 46ddb9e..de11ef8 100644 --- a/jsonschema/src/keywords/pattern.rs +++ b/jsonschema/src/keywords/pattern.rs @@ -6,15 +6,15 @@ use crate::{ primitive_type::PrimitiveType, validator::Validate, }; +use once_cell::sync::Lazy; use serde_json::{Map, Value}; use crate::paths::JSONPointer; use std::ops::Index; -lazy_static::lazy_static! { - // Use regex::Regex here to take advantage of replace_all method not available in fancy_regex::Regex - static ref CONTROL_GROUPS_RE: regex::Regex = regex::Regex::new(r"\\c[A-Za-z]").expect("Is a valid regex"); -} +// Use regex::Regex here to take advantage of replace_all method not available in fancy_regex::Regex +static CONTROL_GROUPS_RE: Lazy = + Lazy::new(|| regex::Regex::new(r"\\c[A-Za-z]").expect("Is a valid regex")); pub(crate) struct PatternValidator { original: String,