-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
first version of defaults injection #1
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wngr I have self-reviewed, should be good to go. See some default_for_schema
test for an example of conjuring a whole instance from thin air. (real code should then validate that instance)
It would also be great if you could give it a spin and compare the performance to version 3.2.0, with and without making use of defaults in a reasonably large example schema. And not that I’m overly worried, but this is some complex stuff, so it might be warranted to let it keep crunching schemas and validations for a few hours while observing memory usage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of reviews. Still wrapping my head around this ..
@@ -37,10 +40,10 @@ impl fmt::Debug for dyn Keyword + 'static { | |||
macro_rules! keyword_key_exists { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by this macro. Looking at the usage, maybe_val
is &serde_json::Value
. How can this work, given that if and else have incompatible types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trick is that the else
branch does not yield a value but returns from the enclosing function — these macros are purely lexical, typechecking happens only after the program has been modified.
@@ -8,7 +8,7 @@ fn visit_specs<F>(dir: &path::Path, cb: F) | |||
where | |||
F: Fn(&path::Path, Value) + Copy, | |||
{ | |||
let contents = fs::read_dir(dir).ok().unwrap(); | |||
let contents = fs::read_dir(dir).expect(&*format!("cannot list directory {:?}", dir)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very helpful for newcomers indeed 🎩
schema.add_defaults_recursive(top, id, scope); | ||
} | ||
|
||
// step 2: use explicit default if present |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not do this before step 1? If you have a default, you don't need to go down into tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of the traversal is not to get a default for this node, it is to mutate the whole subtree to get defaults, too.
@@ -222,6 +325,8 @@ impl Schema { | |||
if let Some(validator) = keyword.keyword.compile(def, context)? { | |||
if is_exclusive_keyword { | |||
validators = vec![validator]; | |||
} else if keyword.keyword.place_first() { | |||
validators.splice(0..0, std::iter::once(validator)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for? This will remove an existing validator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, it replaces the empty range at the beginning of the vector, i.e. pushes to the front.
|
||
// necessary due to object being mutated in the loop | ||
let keys = object.keys().cloned().collect::<Vec<_>>(); | ||
'main: for key in keys.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does that need to be named? you don't seem to break anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left it in because it clarifies the continue
that appears many lines down.
for schema in schemas.iter() { | ||
let mut result = schema.validate_in(&val, path); | ||
if result.is_valid() && result.replacement.is_some() { | ||
*val.to_mut() = result.replacement.take().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't all possible replacements be merged into val
instead of it being overwritten?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed that is the case: notice how the updated &val
will be passed to the next schema two lines up.
Co-Authored-By: Oliver Wangler <oliver@wngr.de>
Co-Authored-By: Oliver Wangler <oliver@wngr.de>
|
||
for url in self.schemes.iter() { | ||
let schema = scope.resolve(url); | ||
// second pass if defaults are enabled to check that the result is stable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is an example of a schema where you might have divergent defaults? And can we add it as a test case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, I shall try to make a small one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good to go from my point of view.
Performance measurements (debug build):
measurements with release build:
Conclusion: about 10% slow-down when not using the new feature. |
what about a feature flag? .. but that's probably up to the maintainers |
…r detail (s-panferov#67) Include the name of the unallowed property name in the errors::Properties details, enabling users to more precisely pin-point the issue in the JSON document.
* feat(json_schema): Draft 7 date and time formats * chore(*): Address warnings * feat(json_schema): Draft 6 JSON pointers * feat(json_schema): Draft 7 IDN hostname Kind of. There's no exclusion between "regular" hostnames and IDNs. * feat(json_schema): Draft 7 conditionals * feat(json_schema): Draft 7 content media type/encoding * feat(json_schema): Draft 7 remaining formats * chore(*): cleanup Co-authored-by: Simon Bihel <simon.bihel@vonage.com>
No description provided.