Skip to content

Commit 303d40a

Browse files
Removed extra method that intercepted desired result
1 parent aa1e2f4 commit 303d40a

4 files changed

Lines changed: 126 additions & 116 deletions

File tree

common/types/memory_tracker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (t *MemoryTracker) Track(val ref.Val) uint32 {
129129
return sz
130130
}
131131

132-
est := t.calc.EstimateAggregateSize(val)
132+
est := t.calc.ApproximateAggregateSize(val)
133133
if est.LimitExceeded {
134134
t.calcLimitExceeded = true
135135
}

common/types/size_calc.go

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -145,30 +145,21 @@ func cacheableAggregateSize(sizer AggregateSizer) bool {
145145
return ok && !status.aggregateSizeLimitExceeded()
146146
}
147147

148-
// AggregateSizeEstimate captures the outcome of an aggregate size computation.
148+
// ApproximateAggregateSize captures the outcome of an aggregate size computation.
149149
//
150150
// The Size saturates at math.MaxUint32 when the accumulated element count overflows uint32.
151151
// LimitExceeded reports the computation was aborted because the value was too expensive to
152152
// traverse (too deep, or too many nodes visited); in that case Size is also math.MaxUint32,
153153
// but the value's true size may be smaller — the two conditions are distinguishable by the flag.
154-
type AggregateSizeEstimate struct {
154+
type ApproximateAggregateSize struct {
155155
Size uint32
156156
LimitExceeded bool
157157
}
158158

159-
// AggregateSize returns the size of the input value, if known.
160-
// Otherwise, a unit size of 1 is returned.
161-
//
162-
// When the calculator's depth or traversal limits are exceeded, the size saturates to
163-
// math.MaxUint32. Use EstimateAggregateSize to distinguish limit-exceeded results from
164-
// genuine uint32 saturation.
165-
func (s *SizeCalculator) AggregateSize(val any) uint32 {
166-
return s.EstimateAggregateSize(val).Size
167-
}
168159

169-
// EstimateAggregateSize returns the aggregate size of the input value along with an indication
160+
// ApproximateAggregateSize returns the aggregate size of the input value along with an indication
170161
// of whether the computation was aborted due to the calculator's depth or traversal limits.
171-
func (s *SizeCalculator) EstimateAggregateSize(val any) AggregateSizeEstimate {
162+
func (s *SizeCalculator) ApproximateAggregateSize(val any) ApproximateAggregateSize {
172163
ctx := sizeContextPool.Get().(*sizeContext)
173164
ctx.calc = s
174165
est := ctx.estimateAggregateSize(val)
@@ -178,6 +169,11 @@ func (s *SizeCalculator) EstimateAggregateSize(val any) AggregateSizeEstimate {
178169
return est
179170
}
180171

172+
// AggregateSize implements the AggregateSizer interface by returning the computed size.
173+
func (s *SizeCalculator) AggregateSize(val any) uint32 {
174+
return s.ApproximateAggregateSize(val).Size
175+
}
176+
181177
// stringSize converts a character or byte length to an element count where stringUnitLength
182178
// characters count as a single element, rounding up with a minimum size of 1.
183179
func (s *SizeCalculator) stringSize(length int) uint32 {
@@ -265,13 +261,13 @@ func (c *sizeContext) aggregateSize(val any) uint32 {
265261
}
266262

267263
// estimateAggregateSize evaluates the aggregate size using this context and resets state.
268-
func (c *sizeContext) estimateAggregateSize(val any) AggregateSizeEstimate {
264+
func (c *sizeContext) estimateAggregateSize(val any) ApproximateAggregateSize {
269265
c.depth = 0
270266
c.traversalCount = 0
271267
c.limitExceeded = false
272268

273269
size := c.AggregateSize(val)
274-
return AggregateSizeEstimate{Size: size, LimitExceeded: c.limitExceeded}
270+
return ApproximateAggregateSize{Size: size, LimitExceeded: c.limitExceeded}
275271
}
276272

277273
func getProtoValueAggregateSize(c *sizeContext, v protoreflect.Value) uint32 {
@@ -385,24 +381,19 @@ func getReflectValueAggregateSize(c *sizeContext, fieldVal reflect.Value) uint32
385381
}
386382
total := safeAddUint32(1, safeUint32FromInt(fieldVal.Len()))
387383
switch elemType.Kind() {
388-
case reflect.String:
384+
case reflect.String, reflect.Struct, reflect.Pointer, reflect.Slice, reflect.Array, reflect.Map, reflect.Interface:
389385
total = 1
390386
for i := 0; i < fieldVal.Len(); i++ {
391-
total = safeAddUint32(total, c.AggregateSize(fieldVal.Index(i).String()))
392-
}
393-
case reflect.Struct, reflect.Pointer, reflect.Slice, reflect.Array, reflect.Map, reflect.Interface:
394-
total = 1
395-
for i := 0; i < fieldVal.Len(); i++ {
396-
total = safeAddUint32(total, c.AggregateSize(fieldVal.Index(i).Interface()))
387+
total = safeAddUint32(total, c.AggregateSize(fieldVal.Index(i)))
397388
}
398389
}
399390
return total
400391
case reflect.Map:
401392
total := uint32(1)
402393
iter := fieldVal.MapRange()
403394
for iter.Next() {
404-
total = safeAddUint32(total, c.AggregateSize(iter.Key().Interface()))
405-
total = safeAddUint32(total, c.AggregateSize(iter.Value().Interface()))
395+
total = safeAddUint32(total, c.AggregateSize(iter.Key()))
396+
total = safeAddUint32(total, c.AggregateSize(iter.Value()))
406397
}
407398
return total
408399
case reflect.Pointer, reflect.Interface:
@@ -431,25 +422,45 @@ func getReflectValueAggregateSize(c *sizeContext, fieldVal reflect.Value) uint32
431422
if !fVal.IsValid() || fVal.IsZero() {
432423
continue
433424
}
434-
total = safeAddUint32(total, c.AggregateSize(fVal.Interface()))
425+
total = safeAddUint32(total, c.AggregateSize(fVal))
435426
}
436427
return total
437428
default:
438429
return 1
439430
}
440431
}
441432

433+
var (
434+
aggregateSizeVisitorType = reflect.TypeFor[AggregateSizeVisitor]()
435+
sizerType = reflect.TypeFor[traits.Sizer]()
436+
protoMessageType = reflect.TypeFor[proto.Message]()
437+
)
438+
442439
func checkCustomSizer(c *sizeContext, fieldVal reflect.Value) (uint32, bool) {
443-
if !fieldVal.CanInterface() {
440+
if !fieldVal.IsValid() || !fieldVal.CanInterface() {
444441
return 0, false
445442
}
446-
447-
switch sizer := fieldVal.Interface().(type) {
448-
case AggregateSizeVisitor:
449-
return sizer.AggregateSize(c), true
450-
case traits.Sizer:
451-
return safeUint32FromBoxedInt(sizer.Size().(Int)), true
452-
default:
453-
return 0, false
443+
t := fieldVal.Type()
444+
if t.Implements(aggregateSizeVisitorType) {
445+
if sizer, ok := fieldVal.Interface().(AggregateSizeVisitor); ok {
446+
return sizer.AggregateSize(c), true
447+
}
448+
}
449+
if t.Implements(sizerType) {
450+
if sizer, ok := fieldVal.Interface().(traits.Sizer); ok {
451+
return safeUint32FromBoxedInt(sizer.Size().(Int)), true
452+
}
453+
}
454+
if t.Implements(protoMessageType) {
455+
if fieldVal.Kind() == reflect.Pointer && fieldVal.IsNil() {
456+
return 0, true
457+
}
458+
if sizer, ok := fieldVal.Interface().(proto.Message); ok {
459+
if sizer == nil {
460+
return 0, true
461+
}
462+
return getProtoMessageAggregateSize(c, sizer.ProtoReflect()), true
463+
}
454464
}
465+
return 0, false
455466
}

0 commit comments

Comments
 (0)