Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Array slices #22

Merged
merged 8 commits into from
Nov 4, 2020
Merged

Array slices #22

merged 8 commits into from
Nov 4, 2020

Conversation

glyn
Copy link
Contributor

@glyn glyn commented Oct 8, 2020

No description provided.

@glyn glyn marked this pull request as draft October 8, 2020 16:11
@glyn glyn requested a review from mkmik October 8, 2020 16:11
@gregsdennis
Copy link
Collaborator

gregsdennis commented Oct 8, 2020

I think we need to add an "optional" property to the tests (or break them out to another section). The "big num" cases can't be supported by all frameworks, and we shouldn't expect it of them. There will be other cars like this as well.

I know we have a "skip" setting, but that means modifying the CTS after I've downloaded it. That should be considered bad practice. The suite should run as-is.

src/ast.rs Outdated
}; // avoid CPU attack
for i in (strt..e).step_by(step as usize) {
if i < len {
sl.push(&arr[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec says:

A negative index j selects an element of an array of length len if and only if 0 <= j + len < len, in which case it selects the same element as the non-negative index j + len.

then it describes the iterations as:

for (i = start; i < end; i = i + step) {
  ...
}

what should happen if you call this on an input slice of length 5?:

    let s = array_slice(j.as_array().unwrap(), -5, 0, 1);

My interpretation is that it would yield

i = -5;
i < 0 //  true
push(arr[i + len]) // arr[-5+5] === arr[0]
i = i+1 //  -4
i < 0 //  true
push(arr[i + len]) // arr[-4+5] === arr[1]
...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good example of a reference implementation and compliance test suite turning up a hole in the spec.

I think the spec should say (only more formally/precisely) that negative start is syntactic sugar for start + len and similarly for negative end. But then start and end need to be desugared before plugging them into the relevant for loop.

So, for an array of length 5, [-5, 0, 1] corresponds to the elements indexed by the values of i in the for loop:

for (i = 0; i < 0; i = i + 1) {
  ...
}

of which there are none, so the result is empty.

Copy link
Member

@mkmik mkmik Oct 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Desugaring before iterating makes most sense to me as well.

I was tinkering with the consequences if doing it the other way around and I don't think it would provide any advantage. An interesting consequence is that it allows the resulting slice to be longer than the input array (and contain repeated elements) which I think would be quite confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the implementation is correct and we just need to fix the spec. ;-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the privileges of a spec writer! :-)

Copy link
Member

@mkmik mkmik Oct 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if something like this would have less special casing: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=dd7180d6586e5a511b4e56b0058e5562

While I don't think it's fully correct w.r.t overflows etc, but has a few advantages:

  1. no temporary array; just uses rust's own array slice iterator and the ability to reverse any iterator
  2. no risk of "cpu attack", since we're not iterating user provided bounds anyway; worst case of bugs we get a panic accessing a slice out of bounds
  3. less duplication of code; the two branches of step > 0 and step < 0 in the PR contain quite a lot of common code with subtle differences

@glyn
Copy link
Contributor Author

glyn commented Oct 12, 2020

I think we need to add an "optional" property to the tests (or break them out to another section). The "big num" cases can't be supported by all frameworks, and we shouldn't expect it of them. There will be other cars like this as well.

The spec is currently silent about supported precisions of array indices. Probably needs firming up in some way.

It's interesting because for any given language or machine architecture, there will exist large values which exceed the built-in capabilities of the language or architecture.

I know we have a "skip" setting, but that means modifying the CTS after I've downloaded it. That should be considered bad practice. The suite should run as-is.

Depending on how the spec pans out, one option would be to add some kind of "category" field to the tests so that those which may be optional in some sense can be skipped en masse. I'm reticent to do that prematurely. Why not clamp the values to a suitable range (e.g. signed 31 bit) for now? Or is that too inconvenient?

@gregsdennis
Copy link
Collaborator

I'm happy for this to merge for now. We can come back to it when the spec addresses it. Let's discuss in your new issue.

@glyn
Copy link
Contributor Author

glyn commented Oct 15, 2020

I'm happy for this to merge for now. We can come back to it when the spec addresses it. Let's discuss in your new issue.

I agree the code is good, but I'd prefer to maintain consistency with the spec. I'll merge this PR once the spec is updated.

@glyn glyn self-assigned this Oct 15, 2020
Co-authored-by: Marko Mikulicic <[email protected]>
@glyn
Copy link
Contributor Author

glyn commented Oct 20, 2020

glyn added 2 commits October 28, 2020 10:49
2^257=231584178474632390847141970017375815706539969331281128078915168015826259279872

will overflow signed 256 bit integers. This can be increased if implementations
surface which can cope with such values.
@glyn glyn requested a review from gregsdennis October 28, 2020 15:12
@glyn
Copy link
Contributor Author

glyn commented Oct 28, 2020

@gregsdennis I'd appreciate your review of the final commit which tests the behaviour when integer representations of array indices and slice parameters overflow. This aims to enforce the current spec.

Copy link
Collaborator

@gregsdennis gregsdennis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the implementation at least attempt to parse the invalid selectors? It looks like cts.rs is just skipping ones that are marked as invalid.

@glyn
Copy link
Contributor Author

glyn commented Oct 29, 2020

@gregsdennis wrote:

Shouldn't the implementation at least attempt to parse the invalid selectors? It looks like cts.rs is just skipping ones that are marked as invalid.

I'm not sure what gives that impression. The parse function of the implementation is executed in the code below from cts.rs regardless of whether the testcase says the selector is invalid:

                let path = jsonpath::parse(&t.selector);

                if let Ok(ref p) = path {

The if statement then tests that parsing failed if and only if the testcase says the selector is invalid.

@gregsdennis
Copy link
Collaborator

Shows how much I know about rust.

@glyn glyn marked this pull request as ready for review November 4, 2020 15:21
@glyn glyn requested review from mkmik and gregsdennis November 4, 2020 15:22
@glyn
Copy link
Contributor Author

glyn commented Nov 4, 2020

I think this is ready to merge now the spec is updated. @mkmik or @gregsdennis: please approve.

@glyn glyn merged commit 85a9fc3 into jsonpath-standard:main Nov 4, 2020
@glyn glyn deleted the array-slices branch November 4, 2020 15:50
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants