From 0ed773af9479cf1bdb4b08f8b93cb3533c692926 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Wed, 14 Jul 2021 13:30:37 +1000 Subject: [PATCH] Sort map entries marshalling dag-json --- codec/dagjson/marshal.go | 20 ++++++++++++++++---- codec/dagjson/roundtripBytes_test.go | 2 +- codec/dagjson/roundtrip_test.go | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/codec/dagjson/marshal.go b/codec/dagjson/marshal.go index 3e292fd..ea0b7a4 100644 --- a/codec/dagjson/marshal.go +++ b/codec/dagjson/marshal.go @@ -3,6 +3,7 @@ package dagjson import ( "encoding/base64" "fmt" + "sort" "github.com/polydawn/refmt/shared" "github.com/polydawn/refmt/tok" @@ -31,21 +32,32 @@ func Marshal(n ipld.Node, sink shared.TokenSink, allowLinks bool) error { if _, err := sink.Step(&tk); err != nil { return err } - // Emit map contents (and recurse). + // Collect map entries, then sort by key + type entry struct { + key string + value ipld.Node + } + entries := []entry{} for itr := n.MapIterator(); !itr.Done(); { k, v, err := itr.Next() if err != nil { return err } - tk.Type = tok.TString - tk.Str, err = k.AsString() + keyStr, err := k.AsString() if err != nil { return err } + entries = append(entries, entry{keyStr, v}) + } + sort.Slice(entries, func(i, j int) bool { return entries[i].key < entries[j].key }) + // Emit map contents (and recurse). + for _, e := range entries { + tk.Type = tok.TString + tk.Str = e.key if _, err := sink.Step(&tk); err != nil { return err } - if err := Marshal(v, sink, allowLinks); err != nil { + if err := Marshal(e.value, sink, allowLinks); err != nil { return err } } diff --git a/codec/dagjson/roundtripBytes_test.go b/codec/dagjson/roundtripBytes_test.go index ccbef3e..a8c05fc 100644 --- a/codec/dagjson/roundtripBytes_test.go +++ b/codec/dagjson/roundtripBytes_test.go @@ -15,7 +15,7 @@ var byteNode = fluent.MustBuildMap(basicnode.Prototype__Map{}, 4, func(na fluent na.AssembleEntry("plain").AssignString("olde string") na.AssembleEntry("bytes").AssignBytes([]byte("deadbeef")) }) -var byteSerial = `{"plain":"olde string","bytes":{"/":{"bytes":"ZGVhZGJlZWY="}}}` +var byteSerial = `{"bytes":{"/":{"bytes":"ZGVhZGJlZWY="}},"plain":"olde string"}` func TestRoundtripBytes(t *testing.T) { t.Run("encoding", func(t *testing.T) { diff --git a/codec/dagjson/roundtrip_test.go b/codec/dagjson/roundtrip_test.go index 1889680..ff64ec2 100644 --- a/codec/dagjson/roundtrip_test.go +++ b/codec/dagjson/roundtrip_test.go @@ -27,7 +27,7 @@ var n = fluent.MustBuildMap(basicnode.Prototype__Map{}, 4, func(na fluent.MapAss }) }) }) -var serial = `{"plain":"olde string","map":{"one":1,"two":2},"list":["three","four"],"nested":{"deeper":["things"]}}` +var serial = `{"list":["three","four"],"map":{"one":1,"two":2},"nested":{"deeper":["things"]},"plain":"olde string"}` func TestRoundtrip(t *testing.T) { t.Run("encoding", func(t *testing.T) { -- GitLab