-
Notifications
You must be signed in to change notification settings - Fork 49
Description
Noticed while discovering ipfs/go-unixfsnode#54
The contract on node.Length() is
go-ipld-prime/datamodel/node.go
Lines 131 to 133 in 65bfa53
| // 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 |
This means that if there is any sort of lazy loading or computation involved in working with a node that is definitely a list or map that there is nothing valid to return.
- Could return
-1but that's a contract violation - Could return some number (e.g. go-unixfsnode's HAMT returns the largest number of entries it can confirm https://github.com/ipfs/go-unixfsnode/blob/364a5496925b291900d67c35b8b898e1a30b7f0a/hamt/shardeddir.go#L262-L289), but that's also a contract violation since the user expects "the number of entries in a map" not "some number <= the number of entries in a map" and the application has no indication that anything has gone wrong.
I suspect the options here are:
- Change
Lengthto return an error - Change the contract to allow
-1to mean any type of error - Add a new function (name TBD) that does return an error and deprecate
Length
While 2 seems the easiest, it has the ability to break a bunch of code without people noticing. Simple compile-time checked fixes like 1 seem a safer option.
Whether 1 or 3 is preferred seems like a matter of taste.
Note: the other functions on the Node interface which could potentially run into a similar issue are Kind(), IsAbsent(), and IsNull() However, it seems like these are less likely to be lazily constructed than Length and therefore less likely to be a problem.
Similarly, the map and list iterators can return errors once they're in use (and they can be checked in advance with Kind()) and so are also less problematic.