Skip to content
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

feat!: Node#Length() now has an error return #532

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions adl/rot13adl/rot13node.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ func (*_R13String) MapIterator() datamodel.MapIterator {
func (*_R13String) ListIterator() datamodel.ListIterator {
return nil
}
func (*_R13String) Length() int64 {
return -1
func (*_R13String) Length() (int64, error) {
return -1, nil
}
func (*_R13String) IsAbsent() bool {
return false
Expand Down
4 changes: 2 additions & 2 deletions adl/rot13adl/rot13substrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (*_Substrate) MapIterator() datamodel.MapIterator {
func (*_Substrate) ListIterator() datamodel.ListIterator {
return nil
}
func (*_Substrate) Length() int64 {
return -1
func (*_Substrate) Length() (int64, error) {
return -1, nil
}
func (*_Substrate) IsAbsent() bool {
return false
Expand Down
31 changes: 22 additions & 9 deletions codec/dagcbor/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
case datamodel.Kind_List:
// Emit start of list.
tk.Type = tok.TArrOpen
l := n.Length()
l, err := n.Length()
if err != nil {
return err
}
tk.Length = int(l) // TODO: overflow check
if _, err := sink.Step(tk); err != nil {
return err
Expand All @@ -87,7 +90,7 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
}
// Emit list close.
tk.Type = tok.TArrClose
_, err := sink.Step(tk)
_, err = sink.Step(tk)
return err
case datamodel.Kind_Bool:
v, err := n.AsBool()
Expand Down Expand Up @@ -174,8 +177,11 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options EncodeOptions) error {
// Emit start of map.
tk.Type = tok.TMapOpen
expectedLength := int(n.Length())
tk.Length = expectedLength // TODO: overflow check
expectedLength, err := n.Length()
if err != nil {
return err
}
tk.Length = int(expectedLength) // TODO: overflow check
if _, err := sink.Step(tk); err != nil {
return err
}
Expand All @@ -197,7 +203,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
}
entries = append(entries, entry{keyStr, v})
}
if len(entries) != expectedLength {
if len(entries) != int(expectedLength) {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
// Apply the desired sort function.
Expand Down Expand Up @@ -229,7 +235,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
}
} else { // no sorting
// Emit map contents (and recurse).
var entryCount int
var entryCount int64
for itr := n.MapIterator(); !itr.Done(); {
k, v, err := itr.Next()
if err != nil {
Expand All @@ -254,7 +260,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
}
// Emit map close.
tk.Type = tok.TMapClose
_, err := sink.Step(tk)
_, err = sink.Step(tk)
return err
}

Expand All @@ -272,7 +278,11 @@ func EncodedLength(n datamodel.Node) (int64, error) {
case datamodel.Kind_Null:
return 1, nil // 0xf6
case datamodel.Kind_Map:
length := uintLength(uint64(n.Length())) // length prefixed major 5
l, err := n.Length()
if err != nil {
return 0, err
}
length := uintLength(uint64(l)) // length prefixed major 5
for itr := n.MapIterator(); !itr.Done(); {
k, v, err := itr.Next()
if err != nil {
Expand All @@ -291,7 +301,10 @@ func EncodedLength(n datamodel.Node) (int64, error) {
}
return length, nil
case datamodel.Kind_List:
nl := n.Length()
nl, err := n.Length()
if err != nil {
return 0, err
}
length := uintLength(uint64(nl)) // length prefixed major 4
for i := int64(0); i < nl; i++ {
v, err := n.LookupByIndex(i)
Expand Down
20 changes: 13 additions & 7 deletions codec/dagjson/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
case datamodel.Kind_Map:
// Emit start of map.
tk.Type = tok.TMapOpen
expectedLength := int(n.Length())
tk.Length = expectedLength // TODO: overflow check
expectedLength, err := n.Length()
if err != nil {
return err
}
tk.Length = int(expectedLength) // TODO: overflow check
if _, err := sink.Step(&tk); err != nil {
return err
}
Expand All @@ -84,7 +87,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
}
entries = append(entries, entry{keyStr, v})
}
if len(entries) != expectedLength {
if len(entries) != int(expectedLength) {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
// Apply the desired sort function.
Expand All @@ -104,7 +107,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
})
}
// Emit map contents (and recurse).
var entryCount int
var entryCount int64
for _, e := range entries {
tk.Type = tok.TString
tk.Str = e.key
Expand Down Expand Up @@ -141,12 +144,15 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
}
// Emit map close.
tk.Type = tok.TMapClose
_, err := sink.Step(&tk)
_, err = sink.Step(&tk)
return err
case datamodel.Kind_List:
// Emit start of list.
tk.Type = tok.TArrOpen
l := n.Length()
l, err := n.Length()
if err != nil {
return err
}
tk.Length = int(l) // TODO: overflow check
if _, err := sink.Step(&tk); err != nil {
return err
Expand All @@ -163,7 +169,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
}
// Emit list close.
tk.Type = tok.TArrClose
_, err := sink.Step(&tk)
_, err = sink.Step(&tk)
return err
case datamodel.Kind_Bool:
v, err := n.AsBool()
Expand Down
3 changes: 2 additions & 1 deletion codecHelpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func Example_unmarshal_withSchema() {
n, err := ipld.Unmarshal(serial, json.Decode, &foobar, typesys.TypeByName("Foobar"))
fmt.Printf("error: %v\n", err)
fmt.Printf("go struct: %v\n", foobar)
fmt.Printf("node kind and length: %s, %d\n", n.Kind(), n.Length())
l, _ := n.Length()
fmt.Printf("node kind and length: %s, %d\n", n.Kind(), l)
fmt.Printf("node lookup 'foo': %q\n", must.String(must.Node(n.LookupByString("foo"))))

// Output:
Expand Down
12 changes: 10 additions & 2 deletions datamodel/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ func Copy(n Node, na NodeAssembler) error {
}
return na.AssignLink(v)
case Kind_Map:
ma, err := na.BeginMap(n.Length())
l, err := n.Length()
if err != nil {
return err
}
ma, err := na.BeginMap(l)
if err != nil {
return err
}
Expand All @@ -89,7 +93,11 @@ func Copy(n Node, na NodeAssembler) error {
}
return ma.Finish()
case Kind_List:
la, err := na.BeginList(n.Length())
l, err := n.Length()
if err != nil {
return err
}
la, err := na.BeginList(l)
if err != nil {
return err
}
Expand Down
20 changes: 18 additions & 2 deletions datamodel/equal.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,15 @@ func DeepEqual(x, y Node) bool {

// Recursive kinds.
case Kind_Map:
if x.Length() != y.Length() {
xl, err := x.Length()
if err != nil {
panic(err)
}
yl, err := y.Length()
if err != nil {
panic(err)
}
if xl != yl {
return false
}
xitr := x.MapIterator()
Expand All @@ -129,7 +137,15 @@ func DeepEqual(x, y Node) bool {
}
return true
case Kind_List:
if x.Length() != y.Length() {
xl, err := x.Length()
if err != nil {
panic(err)
}
yl, err := y.Length()
if err != nil {
panic(err)
}
if xl != yl {
return false
}
xitr := x.ListIterator()
Expand Down
2 changes: 1 addition & 1 deletion datamodel/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ type Node interface {

// Length returns the length of a list, or the number of entries in a map,
// or -1 if the node is not of list nor map kind.
Length() int64
Length() (int64, error)

// Absent nodes are returned when traversing a struct field that is
// defined by a schema but unset in the data. (Absent nodes are not
Expand Down
8 changes: 4 additions & 4 deletions datamodel/unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ func (nullNode) MapIterator() MapIterator {
func (nullNode) ListIterator() ListIterator {
return nil
}
func (nullNode) Length() int64 {
return -1
func (nullNode) Length() (int64, error) {
return -1, nil
}
func (nullNode) IsAbsent() bool {
return false
Expand Down Expand Up @@ -110,8 +110,8 @@ func (absentNode) MapIterator() MapIterator {
func (absentNode) ListIterator() ListIterator {
return nil
}
func (absentNode) Length() int64 {
return -1
func (absentNode) Length() (int64, error) {
return -1, nil
}
func (absentNode) IsAbsent() bool {
return true
Expand Down
3 changes: 2 additions & 1 deletion examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ func Example_unmarshalData() {
n := nb.Build() // Call 'Build' to get the resulting Node. (It's immutable!)

fmt.Printf("the data decoded was a %s kind\n", n.Kind())
fmt.Printf("the length of the node is %d\n", n.Length())
l, _ := n.Length()
fmt.Printf("the length of the node is %d\n", l)

// Output:
// the data decoded was a map kind
Expand Down
24 changes: 18 additions & 6 deletions fluent/fluentBuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ func TestBuild(t *testing.T) {
})
})
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
qt.Check(t, n.Length(), qt.Equals, int64(3))
l, err := n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(3))
qt.Check(t, must.String(must.Node(n.LookupByString("k1"))), qt.Equals, "fine")
qt.Check(t, must.String(must.Node(n.LookupByString("k2"))), qt.Equals, "super")
n = must.Node(n.LookupByString("k3"))
qt.Check(t, n.Length(), qt.Equals, int64(3))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(3))
qt.Check(t, must.String(must.Node(n.LookupByString("k31"))), qt.Equals, "thanks")
qt.Check(t, must.String(must.Node(n.LookupByString("k32"))), qt.Equals, "for")
qt.Check(t, must.String(must.Node(n.LookupByString("k33"))), qt.Equals, "asking")
Expand All @@ -56,16 +60,24 @@ func TestBuild(t *testing.T) {
})
})
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
qt.Check(t, n.Length(), qt.Equals, int64(1))
l, err := n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(1))
n = must.Node(n.LookupByIndex(0))
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
qt.Check(t, n.Length(), qt.Equals, int64(1))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(1))
n = must.Node(n.LookupByIndex(0))
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
qt.Check(t, n.Length(), qt.Equals, int64(1))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(1))
n = must.Node(n.LookupByIndex(0))
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
qt.Check(t, n.Length(), qt.Equals, int64(1))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(1))
n = must.Node(n.LookupByIndex(0))
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Int)
qt.Check(t, must.Int(n), qt.Equals, int64(2))
Expand Down
16 changes: 12 additions & 4 deletions fluent/reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ func TestReflect(t *testing.T) {
qt.Check(t, err, qt.IsNil)
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
t.Run("CorrectContents", func(t *testing.T) {
qt.Check(t, n.Length(), qt.Equals, int64(3))
l, err := n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(3))
qt.Check(t, must.String(must.Node(n.LookupByString("k1"))), qt.Equals, "fine")
qt.Check(t, must.String(must.Node(n.LookupByString("k2"))), qt.Equals, "super")
n := must.Node(n.LookupByString("k3"))
qt.Check(t, n.Length(), qt.Equals, int64(3))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(3))
qt.Check(t, must.String(must.Node(n.LookupByString("k31"))), qt.Equals, "thanks")
qt.Check(t, must.String(must.Node(n.LookupByString("k32"))), qt.Equals, "for")
qt.Check(t, must.String(must.Node(n.LookupByString("k33"))), qt.Equals, "asking")
Expand Down Expand Up @@ -69,11 +73,15 @@ func TestReflect(t *testing.T) {
qt.Check(t, err, qt.IsNil)
qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
t.Run("CorrectContents", func(t *testing.T) {
qt.Check(t, n.Length(), qt.Equals, int64(3))
l, err := n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(3))
qt.Check(t, must.String(must.Node(n.LookupByString("X"))), qt.Equals, "fine")
qt.Check(t, must.String(must.Node(n.LookupByString("Z"))), qt.Equals, "super")
n := must.Node(n.LookupByString("M"))
qt.Check(t, n.Length(), qt.Equals, int64(2))
l, err = n.Length()
qt.Check(t, err, qt.IsNil)
qt.Check(t, l, qt.Equals, int64(2))
qt.Check(t, must.String(must.Node(n.LookupByString("A"))), qt.Equals, "thanks")
qt.Check(t, must.String(must.Node(n.LookupByString("B"))), qt.Equals, "really")
})
Expand Down
12 changes: 10 additions & 2 deletions fluent/toInterfaceValue.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func ToInterface(node datamodel.Node) (interface{}, error) {
case datamodel.Kind_Link:
return node.AsLink()
case datamodel.Kind_Map:
outMap := make(map[string]interface{}, node.Length())
l, err := node.Length()
if err != nil {
return nil, err
}
outMap := make(map[string]interface{}, l)
for mi := node.MapIterator(); !mi.Done(); {
k, v, err := mi.Next()
if err != nil {
Expand All @@ -52,7 +56,11 @@ func ToInterface(node datamodel.Node) (interface{}, error) {
}
return outMap, nil
case datamodel.Kind_List:
outList := make([]interface{}, 0, node.Length())
l, err := node.Length()
if err != nil {
return nil, err
}
outList := make([]interface{}, 0, l)
for li := node.ListIterator(); !li.Done(); {
_, v, err := li.Next()
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion linking/linkingExamples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ func ExampleLinkSystem_Load() {
}

// Tada! We have the data as node that we can traverse and use as desired.
fmt.Printf("we loaded a %s with %d entries\n", n.Kind(), n.Length())
l, _ := n.Length()
fmt.Printf("we loaded a %s with %d entries\n", n.Kind(), l)

// Output:
// we loaded a map with 1 entries
Expand Down
Loading