goprotobuf: Make several changes to ErrRequiredNotSet:
- Report the full or partial path to the first missing required field (where possible) instead of the message name.
- Make it ignorable. Unmarshal and Marshal will continue to decode/encode the full proto.
R=r
CC=golang-dev
https://codereview.appspot.com/13248047
diff --git a/proto/decode.go b/proto/decode.go
index f951c01..705d38d 100644
--- a/proto/decode.go
+++ b/proto/decode.go
@@ -353,6 +353,7 @@
// unmarshalType does the work of unmarshaling a structure.
func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
+ var state errorState
required, reqFields := prop.reqCount, uint64(0)
var err error
@@ -406,7 +407,10 @@
continue
}
}
- err = dec(o, p, base)
+ decErr := dec(o, p, base)
+ if decErr != nil && !state.shouldContinue(decErr, p) {
+ err = decErr
+ }
if err == nil && p.Required {
// Successfully decoded a required field.
if tag <= 64 {
@@ -430,8 +434,14 @@
if is_group {
return io.ErrUnexpectedEOF
}
+ if state.err != nil {
+ return state.err
+ }
if required > 0 {
- return &ErrRequiredNotSet{st}
+ // Not enough information to determine the exact field. If we use extra
+ // CPU, we could determine the field only if the missing required field
+ // has a tag <= 64 and we check reqFields.
+ return &ErrRequiredNotSet{"{Unknown}"}
}
}
return err