-
Notifications
You must be signed in to change notification settings - Fork 915
GODRIVER-3605 Refactor StringN #2128
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,6 @@ package bsoncore | |
import ( | ||
"fmt" | ||
"io" | ||
"math" | ||
"strconv" | ||
"strings" | ||
) | ||
|
@@ -83,55 +82,79 @@ func (a Array) DebugString() string { | |
// String outputs an ExtendedJSON version of Array. If the Array is not valid, this method | ||
// returns an empty string. | ||
func (a Array) String() string { | ||
return a.StringN(math.MaxInt) | ||
str, _ := a.StringN(-1) | ||
return str | ||
} | ||
|
||
// StringN stringifies an array upto N bytes | ||
func (a Array) StringN(n int) string { | ||
if lens, _, _ := ReadLength(a); lens < 5 || n <= 0 { | ||
return "" | ||
// StringN stringifies an array. If N is non-negative, it will truncate the string to N bytes. | ||
// Otherwise, it will return the full string representation. The second return value indicates | ||
// whether the string was truncated or not. | ||
func (a Array) StringN(n int) (string, bool) { | ||
length, rem, ok := ReadLength(a) | ||
if !ok || length < 5 { | ||
return "", false | ||
} | ||
length -= 4 // length bytes | ||
length-- // final null byte | ||
|
||
if n == 0 { | ||
return "", true | ||
} | ||
|
||
var buf strings.Builder | ||
buf.WriteByte('[') | ||
|
||
length, rem, _ := ReadLength(a) // We know we have enough bytes to read the length | ||
length -= 4 | ||
|
||
var truncated bool | ||
var elem Element | ||
var ok bool | ||
|
||
if n > 0 { | ||
for length > 1 { | ||
elem, rem, ok = ReadElement(rem) | ||
|
||
length -= int32(len(elem)) | ||
if !ok { | ||
return "" | ||
} | ||
|
||
str := elem.Value().StringN(n - buf.Len()) | ||
|
||
buf.WriteString(str) | ||
|
||
if buf.Len() == n { | ||
return buf.String() | ||
var str string | ||
first := true | ||
for length > 0 && !truncated { | ||
needStrLen := -1 | ||
// Set needStrLen if n is positive, meaning we want to limit the string length. | ||
if n > 0 { | ||
// Stop stringifying if we reach the limit, that also ensures needStrLen is | ||
// greater than 0 if we need to limit the length. | ||
if buf.Len() >= n { | ||
truncated = true | ||
break | ||
} | ||
needStrLen = n - buf.Len() | ||
} | ||
|
||
if length > 1 { | ||
buf.WriteByte(',') | ||
// Append a comma if this is not the first element. | ||
if !first { | ||
buf.WriteByte(',') | ||
// If we are truncating, we need to account for the comma in the length. | ||
if needStrLen > 0 { | ||
needStrLen-- | ||
if needStrLen == 0 { | ||
truncated = true | ||
break | ||
} | ||
} | ||
} | ||
if length != 1 { // Missing final null byte or inaccurate length | ||
return "" | ||
|
||
elem, rem, ok = ReadElement(rem) | ||
length -= int32(len(elem)) | ||
// Exit on malformed element. | ||
if !ok || length < 0 { | ||
return "", false | ||
} | ||
|
||
// Delegate to StringN() on the element. | ||
str, truncated = elem.Value().StringN(needStrLen) | ||
buf.WriteString(str) | ||
|
||
first = false | ||
} | ||
|
||
if buf.Len()+1 <= n { | ||
if n <= 0 || (buf.Len() < n && !truncated) { | ||
buf.WriteByte(']') | ||
} else { | ||
truncated = true | ||
} | ||
|
||
return buf.String() | ||
return buf.String(), truncated | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to truncate the string in the buffer? E.g. bsoncoreutil.Truncate(buf.String()) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not technically necessary, as the buffer has been truncated previously. However, an extra-truncating sounds like a good idea for an additional layer of security |
||
} | ||
|
||
// Values returns this array as a slice of values. The returned slice will contain valid values. | ||
|
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.
This line causes GODRIVER-3561