-
Notifications
You must be signed in to change notification settings - Fork 6
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
Makes IonSchemaElement use borrowed Elements #222
Conversation
63cb7fc
to
32a6cf5
Compare
Makes IonSchemaElement use borrowed Elements
32a6cf5
to
ec65db9
Compare
let schema = __new_schema_system().load_schema(schema_id).expect(&format!("Expected to load schema: {}", schema_id)); | ||
let isl_type = schema.get_type(type_id).expect(&format!("Expected to get type: {}", type_id)); | ||
let value: ion_rs::Element = ion_rs::Element::read_one(value_ion.as_bytes()).expect(&format!("Expected to be able to read value: {}", value_ion)); |
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.
🗺️ Drive-by improvement to get better failure messages in the test runner.
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 not very familiar with this part of the code--it looks like this is a method that only gets run in testing, so performance may not matter. If so, you can disregard.
These expect(&format!(...))
calls will allocate/format a String
even if the previous method calls succeed. We should use something like Result::unwrap_or_else(|| panic!("Expected ..."))
to sidestep the cost on the happy path.
https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else
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.
It's only in testing.
"imports", | ||
"constraints::ordered_elements", | ||
"constraints::precision", |
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.
🗺️ It turns out that we don't need to skip the tests for precision
any more. However, the fix was in some previous change. All of the other changes in this file are just trying to improve the specificity of the comments.
@@ -93,125 +92,6 @@ const ISL_2_0_KEYWORDS: [&str; 28] = [ | |||
"valid_values", | |||
]; | |||
|
|||
/// Provide an Ion schema Element which includes all Elements and a document type |
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.
🗺️ All of this was moved to ion_schema_element.rs
(and then rewritten).
@@ -156,8 +155,11 @@ impl NfaEvaluation { | |||
} | |||
|
|||
/// Validates provided ordered elements against referenced [Nfa] | |||
pub fn validate_ordered_elements(&mut self, elements: &[Element], type_store: &TypeStore) { | |||
let mut elements_iter = elements.iter().peekable(); | |||
pub fn validate_ordered_elements<'a, T: Iterator<Item = &'a Element>>( |
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 NFA implementation now accepts any iterator over Element
s, rather than requiring a slice of Element
s or being tied to a particular iterator implementation.
// this is just a place holder for document type, | ||
// IonSchemaElement::Document(_) type is used to verify the correctness on the validation side | ||
"type::{ name: document }", |
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.
🗺️ document
is an "atomic" type instead of a "derived" type now that we have IonSchemaElementType::Document
.
let schema = __new_schema_system().load_schema(schema_id).expect(&format!("Expected to load schema: {}", schema_id)); | ||
let isl_type = schema.get_type(type_id).expect(&format!("Expected to get type: {}", type_id)); | ||
let value: ion_rs::Element = ion_rs::Element::read_one(value_ion.as_bytes()).expect(&format!("Expected to be able to read value: {}", value_ion)); |
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 not very familiar with this part of the code--it looks like this is a method that only gets run in testing, so performance may not matter. If so, you can disregard.
These expect(&format!(...))
calls will allocate/format a String
even if the previous method calls succeed. We should use something like Result::unwrap_or_else(|| panic!("Expected ..."))
to sidestep the cost on the happy path.
https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else
@@ -321,18 +321,15 @@ fn generate_preamble(root_dir_path: &Path) -> TokenStream { | |||
|
|||
/// Asserts that a value is or is not valid for a given ISL type. | |||
fn __assert_value_validity_for_type(value_ion: &str, schema_id: &str, type_id: &str, expect_valid: bool) -> Result<(), String> { |
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.
Do you happen to know why we're using a __
prefix rather than, say, making a new submodule to house these functions?
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 wanted to make sure that we didn't have any name conflicts with a generated test case, so I added a __
prefix. I could have added a new submodule, but that probably also would have needed something to reduce the likelihood of a name conflict with a generated test function.
let mut elements_iter = elements.iter().peekable(); | ||
pub fn validate_ordered_elements<'a, T: Iterator<Item = &'a Element>>( | ||
&mut self, | ||
mut elements_iter: Peekable<T>, |
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.
TIL that Peekable
's impl of peekable()
is not specialized to avoid producing a Peekable<Peekable<T>>
.
@@ -267,12 +269,12 @@ impl NfaEvaluation { | |||
// this method iterates through elements to satisfy minimum required occurrences for given transition | |||
// It will return false if an invalid Ion value is found which doesn't satisfy minimum occurrence requirement for given transition | |||
// Otherwise it will return true | |||
fn evaluate_transition_to_self( | |||
fn evaluate_transition_to_self<'a, T: Iterator<Item = &'a Element>>( |
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.
Food for thought: you could create a new trait for this to avoid having to spell out the bounds each time.
// Make an empty extension trait called `ElementIter`...
trait ElementIter<'a>: Iterator<Item = &'a Element> {}
impl<'a, T> ElementIter<'a> for T where T: Iterator<Item = &'a Element> {}
// ...and then replace this:
fn evaluate_transition_to_self<'a, T: Iterator<Item = &'a Element>> (...) {...}
// ...with this:
fn evaluate_transition_to_self<'a, T: ElementIter<'a>>(...) {...}
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.
Yeah, I guess I could. TBH, though, I'm hoping to do a fairly complete rewrite the NFA to get better error messages like in amazon-ion/ion-schema-kotlin#228
Issue #, if available:
Fixes #214
Fixes #137
Description of changes:
Changes
IonSchemaElement
so that it holds references toElement
s rather than owningElement
s. Details in PR tour 🗺️ comments.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.