-
Notifications
You must be signed in to change notification settings - Fork 916
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
base: master
Are you sure you want to change the base?
Conversation
API Change Report./v2/x/bsonx/bsoncoreincompatible changesArray.StringN: changed from func(int) string to func(int) (string, bool) |
f7afe10
to
050c014
Compare
f9a5d13
to
4d17e8b
Compare
d2d4214
to
0563a2b
Compare
|
||
// If the last byte is not a closing bracket, then the document was truncated | ||
if len(str) > 0 && str[len(str)-1] != '}' { |
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
acac4b7
to
620794a
Compare
620794a
to
3d68a75
Compare
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.
Excellent work, Qingyang. Thank you for taking this on 👍
|
||
var buf strings.Builder | ||
// stringN stringify a document. If N is larger than 0, it will truncate the string to N bytes. |
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.
Can we clarify in the method documentation that the second parameter indicates if the stringified document was truncated?
func (d Document) StringN(n int) string { | ||
if len(d) < 5 || n <= 0 { | ||
return "" | ||
func (d Document) StringN(n int) (string, bool) { |
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.
Can we clarify in the method documentation that the second parameter indicates if the stringified document was truncated?
if n <= 0 { | ||
if l, _, ok := ReadLength(d); !ok || l < 5 { | ||
return "", false | ||
} | ||
return "", true | ||
} | ||
return d.stringN(n) |
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.
It's interesting that calling StringN(0)
will return an empty string but stringN(0)
will return the entire document. The asymmetry makes the code fairly difficult to read. Should we update StringN
so that an N <= 0 argument returns the full document?
func (d Document) String(n int) (string, bool) {
if n <= 0 {
return d.stringN(0)
}
return d.stringN(n)
}
Ultimately, it's unclear to me why one would call StringN(0)
expecting an empty string.
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.
By using stringN()
, we can keep the original behavior of StringN(n)
, which is to return an empty string when n <= 0, while also allowing it to be reused by String()
. However, I will be happy to merge stringN()
and StringN()
if we all accept returning the entire document on StringN(0)
.
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.
I think that makes sense. Will let @matthewdale opine.
if !ok || length < 5 { | ||
return "", false | ||
} | ||
length -= (4 /* length bytes */ + 1 /* final null byte */) |
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.
[nit] Can we re-write this to use //
?
length := (4 + // length bytes
1) // final null bytes
truncatedStr := bsoncoreutil.Truncate(str, n-buf.Len()) | ||
buf.WriteString(truncatedStr) | ||
|
||
for length > 0 && !truncated { |
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.
[nit] The loop logic is hard to follow, suggest adding comments. I think the following are sufficient:
- determine remaining budget
l := n - buf.Len()
- If
buf.Len() >= n
, then mark truncated and break - if
!first
, then write comma, then decrementl
and possibly break - ReadElement, subtract its full length, exit on
!ok
- Delegate to
elem.stringN(l)
, write its str, record its truncated flag
l = n - buf.Len() | ||
} | ||
if !first { | ||
buf.WriteByte(',') |
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.
Are we sure we should be writing the comma here? Without testing directly it seems unintuitive. What if n=1
or something and there isn't enough room for a comma?
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.
Another issue is that we don't need a comma if the document only contains one element, even if there is enough space.
for _, tc := range testCases { | ||
for n := -1; n <= len(tc.want)+1; n++ { | ||
t.Run(fmt.Sprintf("StringN %s n==%d", tc.description, n), func(t *testing.T) { | ||
got, _ := tc.doc.StringN(n) |
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.
We should validate the expected values for the the truncation bool.
func (e Element) StringN(n int) string { | ||
func (e Element) StringN(n int) (string, bool) { | ||
if n <= 0 { | ||
return "", len(e) > 0 |
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.
Consider treating n<=0
as "no limit", see comment on document.StringN().
if n <= 0 { | ||
return "" | ||
return "", len(str) > 0 |
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.
Consider treating n<=0 as "no limit", see comment on document.StringN().
if lens, _, _ := ReadLength(a); lens < 5 || n <= 0 { | ||
return "" | ||
func (a Array) StringN(n int) (string, bool) { | ||
if n <= 0 { |
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.
Consider treating n<=0 as "no limit", see comment on document.StringN().
GODRIVER-3605
GODRIVER-3561
Summary
Refactor
StringN
Background & Motivation
Originally,
Element.StringN()
does not truncate strings as expected.This PR also adds a return flag to
StringN()
to indicate whether the string has been truncated.