feat(sprintf): support Go-compatible %q for strings - #809
Open
Vitalii Tverdokhlib (vitaliytv) wants to merge 2 commits into
Open
feat(sprintf): support Go-compatible %q for strings#809Vitalii Tverdokhlib (vitaliytv) wants to merge 2 commits into
Vitalii Tverdokhlib (vitaliytv) wants to merge 2 commits into
Conversation
Go's `%q` verb (strconv.Quote) is used by OPA's sprintf, but regorus currently bails on it unconditionally. Add support for `Value::String` arguments only: wrap in double quotes, escape `"` and `\`, use the short escapes for the common control characters (\a \b \f \n \r \t \v), fall back to \xNN/\uNNNN/\UNNNNNNNN for other non-printable characters, and leave printable (including non-ASCII) characters untouched. Unlike json.marshal, %q does not HTML-escape < > &. %q on non-string values (numbers, bools, etc.) still bails as before - Go's %q on those produces different, single-quoted output that is out of scope for this change. Verified byte-for-byte against real OPA output (strconv.Quote semantics) for quotes, backslashes, control characters, DEL, non-ASCII printable text, and the < > & non-escaping case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Author
|
Follow-up for the complete format-spec parser and broader Go/OPA |
Contributor
Author
|
Would you prefer this change to be reviewed in two stages, or as one larger PR?
#810 is currently stacked on this PR, so its diff against |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add support for Go-syntax
%qformatting for Regorus string values. The implementation now matches Go 1.27.1 / OPA 1.20.2 for the supported string forms:\\xNN/\\uNNNN/\\UNNNNNNNNescapes;<,>, or&;sprintfparser (%Nq,%0Nq, and%.Nq);sprintfoutput buffer and propagates allocator memory-limit errors.Correctness changes
The initial implementation approximated Go's
strconv.IsPrintwith Rust character predicates. That differs for Unicode format characters, private-use characters, noncharacters, and unassigned code points. This revision ports the compact generated tables and lookup algorithm from Go 1.27.1'sstrconv/isprint.go(Unicode 17.0.0), so values such as U+00AD, U+200B, U+E000, U+FDD0, and U+0378 are escaped exactly like Go.Go's
%qapplies string precision before quoting and field width after quoting, both measured in Unicode code points. The supported Regorus forms now do the same, including Unicode input and zero padding.Verification
Compared directly with OPA 1.20.2 (built with Go 1.27.1) for regular strings, every escape class, printable Unicode, the Unicode edge cases above, width, zero padding, precision, and emoji width/precision.
Local checks:
cargo test --lockedcargo test --locked --no-default-features --libcargo check --locked --no-default-featurescargo xtask test-no-std%qcargo clippy --locked --lib --all-features -- -D warningsScope and full Go
%qThis PR intentionally handles
Value::Stringonly and preserves the repository's existing partialsprintfparser. A complete implementation of Go's%qwould also require:%8.3q);+for ASCII-only quoting,#for backquoted strings when allowed, and-for right padding;*,[n]);OPA adds another compatibility layer before calling
fmt.Sprintf: strings remain Go strings, fitting integers become Go integers, while booleans, nulls, arrays, objects, and sets are converted to their OPA string representation. Reproducing all of that is broader than a quoting helper and should be implemented with a proper format-spec parser and explicit OPA value-conversion rules rather than incrementally extending this string-only branch.