diff --git a/internal/evaluator/builder.go b/internal/evaluator/builder.go index c74ba2b..7e4c7e4 100644 --- a/internal/evaluator/builder.go +++ b/internal/evaluator/builder.go @@ -207,18 +207,12 @@ func (bldr *Builder) buildField( Descriptor: fieldDescriptor, Required: fieldConstraints.GetRequired(), IgnoreEmpty: fieldDescriptor.HasPresence() || - fieldConstraints.GetIgnoreEmpty() || - fieldConstraints.GetIgnore() == validate.Ignore_IGNORE_IF_UNPOPULATED || - fieldConstraints.GetIgnore() == validate.Ignore_IGNORE_IF_DEFAULT_VALUE, - IgnoreDefault: fieldDescriptor.HasPresence() && fieldConstraints.GetIgnore() == validate.Ignore_IGNORE_IF_DEFAULT_VALUE, + bldr.shouldIgnoreEmpty(fieldConstraints), + IgnoreDefault: fieldDescriptor.HasPresence() && + bldr.shouldIgnoreDefault(fieldConstraints), } if fld.IgnoreDefault { - if fieldDescriptor.Kind() == protoreflect.MessageKind && fieldDescriptor.Cardinality() != protoreflect.Repeated { - msg := dynamicpb.NewMessage(fieldDescriptor.Message()) - fld.Zero = protoreflect.ValueOfMessage(msg) - } else { - fld.Zero = fieldDescriptor.Default() - } + fld.Zero = bldr.zeroValue(fieldDescriptor, false) } err := bldr.buildValue(fieldDescriptor, fieldConstraints, false, &fld.Value, cache) return fld, err @@ -266,21 +260,9 @@ func (bldr *Builder) processIgnoreEmpty( ) error { // the only time we need to ignore empty on a value is if it's evaluating a // field item (repeated element or map key/value). - val.IgnoreEmpty = forItems && (constraints.GetIgnoreEmpty() || - constraints.GetIgnore() == validate.Ignore_IGNORE_IF_UNPOPULATED || - constraints.GetIgnore() == validate.Ignore_IGNORE_IF_DEFAULT_VALUE) - switch { - case !val.IgnoreEmpty: - // only need the zero value for checking ignore_empty constraint - return nil - case fdesc.IsList(): - msg := dynamicpb.NewMessage(fdesc.ContainingMessage()) - val.Zero = msg.Get(fdesc).List().NewElement() - case fdesc.Kind() == protoreflect.MessageKind: - msg := dynamicpb.NewMessage(fdesc.Message()) - val.Zero = protoreflect.ValueOfMessage(msg) - default: - val.Zero = fdesc.Default() + val.IgnoreEmpty = forItems && bldr.shouldIgnoreEmpty(constraints) + if val.IgnoreEmpty { + val.Zero = bldr.zeroValue(fdesc, forItems) } return nil } @@ -320,9 +302,9 @@ func (bldr *Builder) processEmbeddedMessage( cache MessageCache, ) error { if fdesc.Kind() != protoreflect.MessageKind || - rules.GetSkipped() || - rules.GetIgnore() == validate.Ignore_IGNORE_ALWAYS || - fdesc.IsMap() || (fdesc.IsList() && !forItems) { + bldr.shouldSkip(rules) || + fdesc.IsMap() || + (fdesc.IsList() && !forItems) { return nil } @@ -345,9 +327,9 @@ func (bldr *Builder) processWrapperConstraints( cache MessageCache, ) error { if fdesc.Kind() != protoreflect.MessageKind || - rules.GetSkipped() || - rules.GetIgnore() == validate.Ignore_IGNORE_ALWAYS || - fdesc.IsMap() || (fdesc.IsList() && !forItems) { + bldr.shouldSkip(rules) || + fdesc.IsMap() || + (fdesc.IsList() && !forItems) { return nil } @@ -486,6 +468,35 @@ func (bldr *Builder) processRepeatedConstraints( return nil } +func (bldr *Builder) shouldSkip(constraints *validate.FieldConstraints) bool { + return constraints.GetSkipped() || + constraints.GetIgnore() == validate.Ignore_IGNORE_ALWAYS +} + +func (bldr *Builder) shouldIgnoreEmpty(constraints *validate.FieldConstraints) bool { + return constraints.GetIgnoreEmpty() || + constraints.GetIgnore() == validate.Ignore_IGNORE_IF_UNPOPULATED || + constraints.GetIgnore() == validate.Ignore_IGNORE_IF_DEFAULT_VALUE +} + +func (bldr *Builder) shouldIgnoreDefault(constraints *validate.FieldConstraints) bool { + return constraints.GetIgnore() == validate.Ignore_IGNORE_IF_DEFAULT_VALUE +} + +func (bldr *Builder) zeroValue(fdesc protoreflect.FieldDescriptor, forItems bool) protoreflect.Value { + switch { + case forItems && fdesc.IsList(): + msg := dynamicpb.NewMessage(fdesc.ContainingMessage()) + return msg.Get(fdesc).List().NewElement() + case fdesc.Kind() == protoreflect.MessageKind && + fdesc.Cardinality() != protoreflect.Repeated: + msg := dynamicpb.NewMessage(fdesc.Message()) + return protoreflect.ValueOfMessage(msg) + default: + return fdesc.Default() + } +} + type MessageCache map[protoreflect.MessageDescriptor]*message func (c MessageCache) Clone() MessageCache {