fix(encode): fall back from the literal multiline form when unsafe
Assisted-by: GLM 5.3
This commit is contained in:
@@ -798,12 +798,40 @@ func (e *encoder) writeInlineTable(m map[string]any) error {
|
||||
}
|
||||
|
||||
func (e *encoder) writeStringVal(s string) error {
|
||||
if e.opts.literalMultilineAt > 0 && strings.ContainsRune(s, '\n') && len(s) >= e.opts.literalMultilineAt {
|
||||
if e.opts.literalMultilineAt > 0 && strings.ContainsRune(s, '\n') &&
|
||||
len(s) >= e.opts.literalMultilineAt && canBeLiteralMultiline(s) {
|
||||
return writeLiteralMultilineString(&e.buf, s)
|
||||
}
|
||||
return writeQuotedString(&e.buf, s)
|
||||
}
|
||||
|
||||
// canBeLiteralMultiline reports whether s can be carried verbatim by the
|
||||
// literal ”'...”' form: the form has no escapes, so a run of three single
|
||||
// quotes would close the delimiter early, and control characters beyond tab,
|
||||
// and a carriage return outside a CRLF pair, have no representation at all.
|
||||
// Anything else falls back to the escaped basic string.
|
||||
func canBeLiteralMultiline(s string) bool {
|
||||
if strings.Contains(s, "'''") {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
r, size := utf8.DecodeRuneInString(s[i:])
|
||||
switch {
|
||||
case r == '\t' || r == '\n':
|
||||
case r == '\r':
|
||||
if !strings.HasPrefix(s[i+size:], "\n") {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if r < 0x20 || r == 0x7f {
|
||||
return false
|
||||
}
|
||||
}
|
||||
i += size
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// writeLiteralMultilineString writes s as a TOML literal multi-line string,
|
||||
// surrounded by triple single quotes. The opening delimiter is followed by a
|
||||
// newline that the reader trims, so we always include one. The closing
|
||||
|
||||
Reference in New Issue
Block a user