internal/impl: add fast-path for IsInitialized
This currently returns uninformative errors from the fast path and then
consults the slow, reflection-based path only when an error is detected.
Perhaps it's worth going through the effort of producing better errors
directly on the fast path.
Change-Id: I68536e9438010dbd97dbaff4f47b78430221d94b
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171462
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/encode_map.go b/internal/impl/encode_map.go
index d140b27..5a02c34 100644
--- a/internal/impl/encode_map.go
+++ b/internal/impl/encode_map.go
@@ -25,7 +25,7 @@
keyFuncs := encoderFuncsForValue(keyField, ft.Key())
valFuncs := encoderFuncsForValue(valField, ft.Elem())
- return pointerCoderFuncs{
+ funcs = pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMap(p, tagsize, ft, keyFuncs, valFuncs, opts)
},
@@ -33,6 +33,12 @@
return appendMap(b, p, wiretag, keyWiretag, valWiretag, ft, keyFuncs, valFuncs, opts)
},
}
+ if valFuncs.isInit != nil {
+ funcs.isInit = func(p pointer) error {
+ return isInitMap(p, ft, valFuncs.isInit)
+ }
+ }
+ return funcs
}
const (
@@ -103,6 +109,20 @@
return b, nil
}
+func isInitMap(p pointer, goType reflect.Type, isInit func(interface{}) error) error {
+ m := p.AsValueOf(goType).Elem()
+ if m.Len() == 0 {
+ return nil
+ }
+ iter := mapRange(m)
+ for iter.Next() {
+ if err := isInit(iter.Value().Interface()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
func mapKeys(vs []reflect.Value) sort.Interface {