@@ -18,7 +18,7 @@ package gomatrixserverlib
1818import (
1919 "encoding/binary"
2020 "errors"
21- "sort "
21+ "slices "
2222 "strings"
2323 "unicode/utf16"
2424 "unicode/utf8"
@@ -159,40 +159,33 @@ func CanonicalJSONAssumeValid(input []byte) []byte {
159159// by codepoint. The input must be valid JSON.
160160func SortJSON (input , output []byte ) []byte {
161161 result := gjson .ParseBytes (input )
162-
163- RawJSON := RawJSONFromResult (result , input )
164- return sortJSONValue (result , RawJSON , output )
162+ return sortJSONValue (result , output )
165163}
166164
167165// sortJSONValue takes a gjson.Result and sorts it. inputJSON must be the
168166// raw JSON bytes that gjson.Result points to.
169- func sortJSONValue (input gjson.Result , inputJSON , output []byte ) []byte {
167+ func sortJSONValue (input gjson.Result , output []byte ) []byte {
170168 if input .IsArray () {
171- return sortJSONArray (input , inputJSON , output )
169+ return sortJSONArray (input , output )
172170 }
173-
174171 if input .IsObject () {
175- return sortJSONObject (input , inputJSON , output )
172+ return sortJSONObject (input , output )
176173 }
177-
178174 // If its neither an object nor an array then there is no sub structure
179175 // to sort, so just append the raw bytes.
180- return append (output , inputJSON ... )
176+ return append (output , input . Raw ... )
181177}
182178
183179// sortJSONArray takes a gjson.Result and sorts it, assuming its an array.
184180// inputJSON must be the raw JSON bytes that gjson.Result points to.
185- func sortJSONArray (input gjson.Result , inputJSON , output []byte ) []byte {
181+ func sortJSONArray (input gjson.Result , output []byte ) []byte {
186182 sep := byte ('[' )
187183
188184 // Iterate over each value in the array and sort it.
189185 input .ForEach (func (_ , value gjson.Result ) bool {
190186 output = append (output , sep )
191187 sep = ','
192-
193- RawJSON := RawJSONFromResult (value , inputJSON )
194- output = sortJSONValue (value , RawJSON , output )
195-
188+ output = sortJSONValue (value , output )
196189 return true // keep iterating
197190 })
198191
@@ -209,29 +202,30 @@ func sortJSONArray(input gjson.Result, inputJSON, output []byte) []byte {
209202
210203// sortJSONObject takes a gjson.Result and sorts it, assuming its an object.
211204// inputJSON must be the raw JSON bytes that gjson.Result points to.
212- func sortJSONObject (input gjson.Result , inputJSON , output []byte ) []byte {
205+ func sortJSONObject (input gjson.Result , output []byte ) []byte {
213206 type entry struct {
214- key string // The parsed key string
215- rawKey []byte // The raw, unparsed key JSON string
216- value gjson.Result
207+ key string // The parsed key string
208+ value gjson.Result
217209 }
218210
219- var entries []entry
211+ // Try to stay on the stack here if we can.
212+ var _entries [128 ]entry
213+ entries := _entries [:0 ]
220214
221215 // Iterate over each key/value pair and add it to a slice
222216 // that we can sort
223217 input .ForEach (func (key , value gjson.Result ) bool {
224218 entries = append (entries , entry {
225- key : key .String (),
226- rawKey : RawJSONFromResult (key , inputJSON ),
227- value : value ,
219+ key : key .String (),
220+ value : value ,
228221 })
229222 return true // keep iterating
230223 })
231224
232- // Sort the slice based on the *parsed* key
233- sort .Slice (entries , func (a , b int ) bool {
234- return entries [a ].key < entries [b ].key
225+ // Using slices.SortFunc here instead of sort.Slice avoids
226+ // heap escapes due to reflection.
227+ slices .SortFunc (entries , func (a , b entry ) int {
228+ return strings .Compare (a .key , b .key )
235229 })
236230
237231 sep := byte ('{' )
@@ -241,12 +235,10 @@ func sortJSONObject(input gjson.Result, inputJSON, output []byte) []byte {
241235 sep = ','
242236
243237 // Append the raw unparsed JSON key, *not* the parsed key
244- output = append (output , entry .rawKey ... )
245- output = append (output , ':' )
246-
247- RawJSON := RawJSONFromResult (entry .value , inputJSON )
248-
249- output = sortJSONValue (entry .value , RawJSON , output )
238+ output = append (output , '"' )
239+ output = append (output , entry .key ... )
240+ output = append (output , '"' , ':' )
241+ output = sortJSONValue (entry .value , output )
250242 }
251243 if sep == '{' {
252244 // If sep is still '{' then the object was empty and we never wrote the
@@ -375,10 +367,3 @@ func readHexDigits(input []byte) rune {
375367 hex |= hex >> 8
376368 return rune (hex & 0xFFFF )
377369}
378-
379- // RawJSONFromResult extracts the raw JSON bytes pointed to by result.
380- // input must be the json bytes that were used to generate result
381- // TODO: Why do we do this?
382- func RawJSONFromResult (result gjson.Result , _ []byte ) []byte {
383- return []byte (result .Raw )
384- }
0 commit comments