github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/validator/validator__map.go (about)

     1  package validator
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  
     8  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/errors"
     9  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/rules"
    10  )
    11  
    12  var (
    13  	TargetMapLength = "map length"
    14  )
    15  
    16  type Map struct {
    17  	MinProperties uint64
    18  	MaxProperties *uint64
    19  
    20  	KeyValidator  Validator
    21  	ElemValidator Validator
    22  }
    23  
    24  func init() { DefaultFactory.Register(&Map{}) }
    25  
    26  func (Map) Names() []string { return []string{"map"} }
    27  
    28  func (vm *Map) Validate(v interface{}) error {
    29  	switch rv := v.(type) {
    30  	case reflect.Value:
    31  		return vm.ValidateReflectValue(rv)
    32  	default:
    33  		return vm.ValidateReflectValue(reflect.ValueOf(v))
    34  	}
    35  }
    36  
    37  func (vm *Map) ValidateReflectValue(rv reflect.Value) error {
    38  	length := uint64(0)
    39  	if !rv.IsNil() {
    40  		length = uint64(rv.Len())
    41  	}
    42  
    43  	if length < vm.MinProperties {
    44  		return &errors.OutOfRangeError{
    45  			Target:  TargetMapLength,
    46  			Current: rv.Interface(),
    47  			Minimum: vm.MinProperties,
    48  		}
    49  	}
    50  
    51  	if vm.MaxProperties != nil && length > *vm.MaxProperties {
    52  		return &errors.OutOfRangeError{
    53  			Target:  TargetMapLength,
    54  			Current: rv.Interface(),
    55  			Maximum: vm.MaxProperties,
    56  		}
    57  	}
    58  
    59  	if vm.KeyValidator != nil || vm.ElemValidator != nil {
    60  		errs := errors.NewErrorSet()
    61  		for _, key := range rv.MapKeys() {
    62  			vk := key.Interface()
    63  			if vm.KeyValidator != nil {
    64  				err := vm.KeyValidator.Validate(vk)
    65  				if err != nil {
    66  					errs.AddErr(err, fmt.Sprintf("%v/key", vk))
    67  				}
    68  			}
    69  			if vm.ElemValidator != nil {
    70  				err := vm.ElemValidator.Validate(rv.MapIndex(key).Interface())
    71  				if err != nil {
    72  					errs.AddErr(err, fmt.Sprintf("%v", vk))
    73  				}
    74  			}
    75  		}
    76  		return errs.Err()
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (vm *Map) New(ctx context.Context, r *Rule) (Validator, error) {
    83  	if r.Type.Kind() != reflect.Map {
    84  		return nil, errors.NewUnsupportedTypeError(r.String(), vm.String())
    85  	}
    86  
    87  	ret := &Map{}
    88  
    89  	if r.ExclusiveMin || r.ExclusiveMax {
    90  		return nil, errors.NewSyntaxError(
    91  			"range mark of %s should not be `(` or `)`", ret.Names()[0],
    92  		)
    93  	}
    94  
    95  	min, max, err := UintRuleRange(r, "size of map", 64)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	ret.MinProperties, ret.MaxProperties = min, max
   100  
   101  	k, v, err := MapRuleParam(ctx, r)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	ret.KeyValidator = k
   106  	ret.ElemValidator = v
   107  
   108  	return ret, nil
   109  }
   110  
   111  func (vm *Map) String() string {
   112  	rule := rules.NewRule(vm.Names()[0])
   113  
   114  	if vm.KeyValidator != nil || vm.ElemValidator != nil {
   115  		rule.Params = make([]rules.Node, 2)
   116  
   117  		if vm.KeyValidator != nil {
   118  			rule.Params[0] = rules.NewLiteral([]byte(vm.KeyValidator.String()))
   119  		}
   120  
   121  		if vm.ElemValidator != nil {
   122  			rule.Params[1] = rules.NewLiteral([]byte(vm.ElemValidator.String()))
   123  		}
   124  	}
   125  
   126  	rule.Range = RangeFromUint(vm.MinProperties, vm.MaxProperties)
   127  
   128  	return string(rule.Bytes())
   129  }