From 1930bab51e48a8dcee8b76b9a2b4cc3868ac8d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Mon, 17 Jan 2022 21:46:56 +0000 Subject: [PATCH] node/bindnode: subtract all absents in Length at the repr level For structs at the repr level, we were only subtracting the number of trailing absents, which isn't right. Rod's added checks in the codecs caught this as a failure, thanks to the node/tests suite already having one such case. --- node/bindnode/repr.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/node/bindnode/repr.go b/node/bindnode/repr.go index 39473ea5..dcc3da54 100644 --- a/node/bindnode/repr.go +++ b/node/bindnode/repr.go @@ -234,6 +234,7 @@ func (w *_nodeRepr) MapIterator() datamodel.MapIterator { switch stg := reprStrategy(w.schemaType).(type) { case schema.StructRepresentation_Map: itr := (*_node)(w).MapIterator().(*_structIterator) + // When we reach the last non-absent field, we should stop. itr.reprEnd = int(w.lengthMinusTrailingAbsents()) return (*_structIteratorRepr)(itr) case schema.UnionRepresentation_Keyed: @@ -291,6 +292,17 @@ func (w *_listIteratorRepr) Done() bool { return w.nextIndex >= w.val.Len() } +func (w *_nodeRepr) lengthMinusAbsents() int64 { + fields := w.schemaType.(*schema.TypeStruct).Fields() + n := int64(len(fields)) + for i, field := range fields { + if field.IsOptional() && w.val.Field(i).IsNil() { + n-- + } + } + return n +} + func (w *_nodeRepr) lengthMinusTrailingAbsents() int64 { fields := w.schemaType.(*schema.TypeStruct).Fields() for i := len(fields) - 1; i >= 0; i-- { @@ -307,9 +319,9 @@ func (w *_nodeRepr) Length() int64 { case schema.StructRepresentation_Stringjoin: return -1 case schema.StructRepresentation_Map: - return w.lengthMinusTrailingAbsents() + return w.lengthMinusAbsents() case schema.StructRepresentation_Tuple: - return w.lengthMinusTrailingAbsents() + return w.lengthMinusAbsents() case schema.UnionRepresentation_Keyed: return (*_node)(w).Length() case schema.UnionRepresentation_Kinded: