@@ -9,6 +9,7 @@ package bsoncore
99import (
1010 "fmt"
1111 "io"
12+ "math"
1213 "strconv"
1314 "strings"
1415)
@@ -82,79 +83,55 @@ func (a Array) DebugString() string {
8283// String outputs an ExtendedJSON version of Array. If the Array is not valid, this method
8384// returns an empty string.
8485func (a Array ) String () string {
85- str , _ := a .StringN (- 1 )
86- return str
86+ return a .StringN (math .MaxInt )
8787}
8888
89- // StringN stringifies an array. If N is non-negative, it will truncate the string to N bytes.
90- // Otherwise, it will return the full string representation. The second return value indicates
91- // whether the string was truncated or not.
92- func (a Array ) StringN (n int ) (string , bool ) {
93- length , rem , ok := ReadLength (a )
94- if ! ok || length < 5 {
95- return "" , false
96- }
97- length -= 4 // length bytes
98- length -- // final null byte
99-
100- if n == 0 {
101- return "" , true
89+ // StringN stringifies an array upto N bytes
90+ func (a Array ) StringN (n int ) string {
91+ if lens , _ , _ := ReadLength (a ); lens < 5 || n <= 0 {
92+ return ""
10293 }
10394
10495 var buf strings.Builder
10596 buf .WriteByte ('[' )
10697
107- var truncated bool
98+ length , rem , _ := ReadLength (a ) // We know we have enough bytes to read the length
99+ length -= 4
100+
108101 var elem Element
109- var str string
110- first := true
111- for length > 0 && ! truncated {
112- needStrLen := - 1
113- // Set needStrLen if n is positive, meaning we want to limit the string length.
114- if n > 0 {
115- // Stop stringifying if we reach the limit, that also ensures needStrLen is
116- // greater than 0 if we need to limit the length.
117- if buf .Len () >= n {
118- truncated = true
119- break
120- }
121- needStrLen = n - buf .Len ()
122- }
102+ var ok bool
123103
124- // Append a comma if this is not the first element.
125- if ! first {
126- buf .WriteByte (',' )
127- // If we are truncating, we need to account for the comma in the length.
128- if needStrLen > 0 {
129- needStrLen --
130- if needStrLen == 0 {
131- truncated = true
132- break
133- }
104+ if n > 0 {
105+ for length > 1 {
106+ elem , rem , ok = ReadElement (rem )
107+
108+ length -= int32 (len (elem ))
109+ if ! ok {
110+ return ""
134111 }
135- }
136112
137- elem , rem , ok = ReadElement (rem )
138- length -= int32 (len (elem ))
139- // Exit on malformed element.
140- if ! ok || length < 0 {
141- return "" , false
142- }
113+ str := elem .Value ().StringN (n - buf .Len ())
114+
115+ buf .WriteString (str )
143116
144- // Delegate to StringN () on the element.
145- str , truncated = elem . Value (). StringN ( needStrLen )
146- buf . WriteString ( str )
117+ if buf . Len () == n {
118+ return buf . String ( )
119+ }
147120
148- first = false
121+ if length > 1 {
122+ buf .WriteByte (',' )
123+ }
124+ }
125+ if length != 1 { // Missing final null byte or inaccurate length
126+ return ""
127+ }
149128 }
150129
151- if n <= 0 || ( buf .Len () < n && ! truncated ) {
130+ if buf .Len ()+ 1 <= n {
152131 buf .WriteByte (']' )
153- } else {
154- truncated = true
155132 }
156133
157- return buf .String (), truncated
134+ return buf .String ()
158135}
159136
160137// Values returns this array as a slice of values. The returned slice will contain valid values.
0 commit comments