Skip to content
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

Add 'importbin' statement #584

Merged
merged 3 commits into from
Mar 3, 2022
Merged

Add 'importbin' statement #584

merged 3 commits into from
Mar 3, 2022

Conversation

anguslees
Copy link
Contributor

Add importbin statement. Similar to importstr but the result is an array of numbers (all integers 0-255).

@@ -217,6 +217,8 @@ func calcTP(node ast.Node, varAt map[ast.Node]*common.Variable, g *typeGraph) ty
return tpRef(g.getExprPlaceholder(imported))
case *ast.ImportStr:
return tpRef(stringType)
case *ast.ImportBin:
return tpRef(anyArrayType)
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 wasn't confident on this line - is this correct? Is there a better value to return?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's correct, but it would be better to return an array of numbers specifically. We can add another hardcoded type for this (alongside anyArrayType):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the hints. Added numberArrayType and a testcase.

@coveralls
Copy link

coveralls commented Jan 23, 2022

Coverage Status

Coverage decreased (-0.1%) to 67.694% when pulling 26c3f96 on anguslees:importbin into fb6c700 on google:master.

@sbarzowski
Copy link
Collaborator

Good stuff. We need C++ support before documenting this, but it's not a blocker for merging this here.

@sparkprime
Copy link
Member

Strategically, I'm tempted to say we could merge this without C++ support and document that as an explicit limitation of the C++ implementation. What do you think?

return *c.data
}

// MakeContents creates Contents from a string.
func MakeContents(s string) Contents {
data := []byte(s)
Copy link
Contributor Author

@anguslees anguslees Jan 24, 2022

Choose a reason for hiding this comment

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

It suddenly occurred to me that this probably breaks the 'repeated MakeContents(foo) produces the exact same Contents' rule. Might need to change the Contents representation to store both a []byte pointer and a string pointer, or improve the 'is the same' check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

False alarm? I think there's no problem here, and we're good to proceed.


More info: I think we get a different Contents even when called with the same string, ie:

foo := "foo"
a, b := MakeContents(foo), MakeContents(foo)
a != b

... because of the above line of code ... but afaics this is ok.

Afaics the intended semantics (enforced by importCache.importData()) are that Importer.Import returns a copy of the same Contents object for the same foundAt value -- not a new Contents object made from the same string (subtle difference).

ie: Importer.Import() is meant to do this:

// Good example
func (i *myimporter) ImportData(from, path string) (contents Contents, foundAt string, err error) {
        foundAt = i.resolvePath(from, path)
        if contents = i.cache[foundAt]; contents == nil {
                contents = MakeContents(i.readContents(foundAt))
                // Important! Return (a copy of) the same `Contents` for a given `foundAt`
                i.cache[foundAt] = contents
        }
        return
}

Not this:

// Wrong/bad example
func (i *myimporter) ImportData(from, path string) (contents Contents, foundAt string, err error) {
        foundAt = i.resolvePath(from, path)
        var stringData string
        if stringData, ok = i.dataCache[foundAt]; !ok {
                stringData = i.readContents(foundAt)
                i.dataCache[foundAt] = stringData
        }
        // Wrong! Now we have a 'new' Contents object for the same `foundAt`
        contents = MakeContents(stringData)
        return
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, exactly. We enforce that it's the same Contents object.

(It encourages efficient caching by avoiding unnecessary copies and we can quickly compare pointers for equality instead of going over the whole string).

@sbarzowski
Copy link
Collaborator

Strategically, I'm tempted to say we could merge this without C++ support and document that as an explicit limitation of the C++ implementation. What do you think?

Here are the options I see:
(a) Merge this and then implement importbin on C++ side (which shouldn't be very hard).
(b) Deprecate the C++ implementation and don't spend much effort porting features there anymore (while enforcing that everything that works on C++ side, works in go-jsonnet as well). I wouldn't make an exception just for importbin. Either we want feature-compatibility or we drop it.

Add `importbin` statement.  Similar to `importstr` but the result is
an array of numbers (all integers 0-255).
Add `numberArrayType` specialised type for cases where we know we have
an array of numbers.  Use in some stdlib functions and `importbin`.
@anguslees
Copy link
Contributor Author

C++ PR: google/jsonnet#976

I note there's a Rust PR already in flight too CertainLach/jrsonnet#77. The Rust implementation looks very nice. As a long-term support plan, I vote for dropping the C++ library in favour of the Rust-produced C bindings. We can discuss which project (go or Rust) produces the 'official' /usr/bin/jsonnet CLI tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants