Skip to content

Commit

Permalink
no need to sort, fields are already ordered
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Apr 6, 2021
1 parent 96fd5f9 commit d302379
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 68 deletions.
27 changes: 7 additions & 20 deletions runtime/interpreter/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"fmt"
"io"
"math/big"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -808,25 +807,12 @@ func (e *Encoder) prepareCompositeValue(
interface{},
error,
) {
fieldPairs := v.Fields.pairs
fieldLen := len(fieldPairs)
fields := make(cborArray, v.Fields.Len()*2)

// Sort field names lexicographically.
fieldNames := make([]string, fieldLen)

index := 0
for name := range fieldPairs {
fieldNames[index] = name
index++
}

sort.Strings(fieldNames)

// Create fields (key and value) array, sorted by field name.
fields := make(cborArray, fieldLen*2)

for i, fieldName := range fieldNames {
value := fieldPairs[fieldName].Value
i := 0
for pair := v.Fields.Oldest(); pair != nil; pair = pair.Next() {
fieldName := pair.Key
value := pair.Value

valuePath := append(path[:], fieldName)

Expand All @@ -835,7 +821,8 @@ func (e *Encoder) prepareCompositeValue(
return nil, err
}

fields[i*2], fields[i*2+1] = fieldName, prepared
fields[i], fields[i+1] = fieldName, prepared
i += 2
}

location, err := e.prepareLocation(v.Location)
Expand Down
152 changes: 104 additions & 48 deletions runtime/tests/interpreter/interpreter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7918,11 +7918,11 @@ func TestInterpretForce(t *testing.T) {
})
}

func permutations(xs []string) (res [][]string) {
var f func([]string, int)
f = func(a []string, k int) {
func permutations(xs [][]byte) (res [][][]byte) {
var f func([][]byte, int)
f = func(a [][]byte, k int) {
if k == len(a) {
res = append(res, append([]string{}, a...))
res = append(res, append([][]byte{}, a...))
} else {
for i := k; i < len(xs); i++ {
a[k], a[i] = a[i], a[k]
Expand All @@ -7941,43 +7941,92 @@ func TestInterpretCompositeValueFieldEncodingOrder(t *testing.T) {

t.Parallel()

fieldValues := map[string]int{
"a": 1,
"b": 2,
"c": 3,
fieldValues := map[byte]byte{
'a': 1,
'b': 2,
'c': 3,
}

initializations := make([]string, 0, len(fieldValues))
// prepare initialization statements

initializations := make([][]byte, 0, len(fieldValues))
expectedEncodings := make([][]byte, 0, len(fieldValues))

for name, value := range fieldValues {
initialization := fmt.Sprintf("self.%s = %d", name, value)
initializations = append(initializations, initialization)
initialization := fmt.Sprintf("self.%c = %d", name, value)
initializations = append(initializations, []byte(initialization))

expectedEncodings = append(expectedEncodings, []byte{
// UTF-8 string, length 1
0x61,
name,
// tag
0xD8, 0x98,
// - positive bignum
0xc2,
// - byte string, length 1
0x41,
value,
})
}

allInitializations := permutations(initializations)
allExpectedEncodings := permutations(expectedEncodings)

encodings := make([][]byte, len(allInitializations))
expectedPrefix := []byte{
// tag
0xd8, 0x84,
// array, 5 items follow
0x85,

// tag
0xd8, 0xc1,
// UTF-8 string, length 4
0x64,
// t, e, s, t
0x74, 0x65, 0x73, 0x74,

// nil
0xf6,

// positive integer 1
0x1,

// array, 6 items follow
0x86,
}

expectedSuffix := []byte{
// UTF-8 string, length 4
0x64,
0x54, 0x65, 0x73, 0x74,
}

for i, initialization := range allInitializations {

inter := parseCheckAndInterpret(t,
fmt.Sprintf(
`
struct Test {
let a: Int
let b: Int
let c: Int
var codeBuilder strings.Builder
codeBuilder.WriteString(`
struct Test {
let a: Int
let b: Int
let c: Int
init() {
%s
}
}
init() {
`)

let test = Test()
`,
strings.Join(initialization, "\n"),
),
)
for _, statement := range initialization {
codeBuilder.Write(statement)
codeBuilder.WriteRune('\n')
}

codeBuilder.WriteString(`
}
}
let test = Test()
`)

inter := parseCheckAndInterpret(t, codeBuilder.String())

test := inter.Globals["test"].GetValue().(*interpreter.CompositeValue)

Expand All @@ -7988,13 +8037,15 @@ func TestInterpretCompositeValueFieldEncodingOrder(t *testing.T) {
encoded, _, err := interpreter.EncodeValue(test, nil, false, nil)
require.NoError(t, err)

encodings[i] = encoded
}
expected := expectedPrefix[:]

for _, expectedEncoding := range allExpectedEncodings[i] {
expected = append(expected, expectedEncoding...)
}

expected := encodings[0]
expected = append(expected, expectedSuffix...)

for _, actual := range encodings[1:] {
require.Equal(t, expected, actual)
assert.Equal(t, expected, encoded)
}
}

Expand All @@ -8008,29 +8059,34 @@ func TestInterpretDictionaryValueEncodingOrder(t *testing.T) {
"c": 3,
}

initializations := make([]string, 0, len(fieldValues))
initializations := make([][]byte, 0, len(fieldValues))

for name, value := range fieldValues {
initialization := fmt.Sprintf(`xs["%s"] = %d`, name, value)
initializations = append(initializations, initialization)
initializations = append(initializations, []byte(initialization))
}

for _, initialization := range permutations(initializations) {

inter := parseCheckAndInterpret(t,
fmt.Sprintf(
`
fun construct(): {String: Int} {
let xs: {String: Int} = {}
%s
return xs
}
var codeBuilder strings.Builder
codeBuilder.WriteString(`
fun construct(): {String: Int} {
let xs: {String: Int} = {}
`)

let test = construct()
`,
strings.Join(initialization, "\n"),
),
)
for _, statement := range initialization {
codeBuilder.Write(statement)
codeBuilder.WriteRune('\n')
}

codeBuilder.WriteString(`
return xs
}
let test = construct()
`)

inter := parseCheckAndInterpret(t, codeBuilder.String())

test := inter.Globals["test"].GetValue().(*interpreter.DictionaryValue)

Expand Down

0 comments on commit d302379

Please sign in to comment.