...

Source file src/go.einride.tech/aip/validation/messagevalidator.go

Documentation: go.einride.tech/aip/validation

     1  package validation
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"google.golang.org/genproto/googleapis/rpc/errdetails"
     9  )
    10  
    11  // MessageValidator provides primitives for validating the fields of a message.
    12  type MessageValidator struct {
    13  	parentField     string
    14  	fieldViolations []*errdetails.BadRequest_FieldViolation
    15  }
    16  
    17  // SetParentField sets a parent field which will be prepended to all the subsequently added violations.
    18  func (m *MessageValidator) SetParentField(parentField string) {
    19  	m.parentField = parentField
    20  }
    21  
    22  // AddFieldViolation adds a field violation to the message validator.
    23  func (m *MessageValidator) AddFieldViolation(field, description string, formatArgs ...interface{}) {
    24  	if m.parentField != "" {
    25  		field = makeFieldWithParent(m.parentField, field)
    26  	}
    27  	if len(formatArgs) > 0 {
    28  		description = fmt.Sprintf(description, formatArgs...)
    29  	}
    30  	m.fieldViolations = append(m.fieldViolations, &errdetails.BadRequest_FieldViolation{
    31  		Field:       field,
    32  		Description: description,
    33  	})
    34  }
    35  
    36  // AddFieldError adds a field violation from the provided error.
    37  // If the provided error is a validation.Error, the individual field violations from the provided error are added.
    38  func (m *MessageValidator) AddFieldError(field string, err error) {
    39  	var errValidation *Error
    40  	if errors.As(err, &errValidation) {
    41  		// Add the child field violations with the current field as parent.
    42  		originalParentField := m.parentField
    43  		m.parentField = makeFieldWithParent(m.parentField, field)
    44  		for _, fieldViolation := range errValidation.fieldViolations {
    45  			m.AddFieldViolation(fieldViolation.GetField(), fieldViolation.GetDescription())
    46  		}
    47  		m.parentField = originalParentField
    48  	} else {
    49  		m.AddFieldViolation(field, err.Error())
    50  	}
    51  }
    52  
    53  // Err returns the validator's current validation error, or nil if no field validations have been registered.
    54  func (m *MessageValidator) Err() error {
    55  	if len(m.fieldViolations) > 0 {
    56  		return NewError(m.fieldViolations)
    57  	}
    58  	return nil
    59  }
    60  
    61  func makeFieldWithParent(parentField, field string) string {
    62  	if parentField == "" {
    63  		return field
    64  	}
    65  	var result strings.Builder
    66  	result.Grow(len(parentField) + 1 + len(field))
    67  	_, _ = result.WriteString(parentField)
    68  	_ = result.WriteByte('.')
    69  	_, _ = result.WriteString(field)
    70  	return result.String()
    71  }
    72  

View as plain text