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

     1  package validator
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  
     9  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/errors"
    10  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/rules"
    11  	"github.com/machinefi/w3bstream/pkg/depends/x/typesx"
    12  )
    13  
    14  type Uint struct {
    15  	BitSize uint
    16  
    17  	Minimum          uint64
    18  	Maximum          uint64
    19  	MultipleOf       uint64
    20  	ExclusiveMaximum bool
    21  	ExclusiveMinimum bool
    22  
    23  	Enums map[uint64]string
    24  }
    25  
    26  func init() { DefaultFactory.Register(&Uint{}) }
    27  
    28  func (Uint) Names() []string {
    29  	return []string{"uint", "uint8", "uint16", "uint32", "uint64"}
    30  }
    31  
    32  func (vu *Uint) SetDefault() {
    33  	if vu != nil {
    34  		if vu.BitSize == 0 {
    35  			vu.BitSize = 32
    36  		}
    37  		if vu.Maximum == 0 {
    38  			vu.Maximum = MaxUint(vu.BitSize)
    39  		}
    40  	}
    41  }
    42  
    43  var TargetUintValue = "uint value"
    44  
    45  func (vu *Uint) Validate(v interface{}) error {
    46  	rv, ok := v.(reflect.Value)
    47  	if !ok {
    48  		rv = reflect.ValueOf(v)
    49  	}
    50  
    51  	if k := rv.Type().Kind(); !typesx.IsUnsignedIntReflectKind(k) {
    52  		return errors.NewUnsupportedTypeError(rv.Type().String(), vu.String())
    53  	}
    54  
    55  	val := rv.Uint()
    56  
    57  	if vu.Enums != nil {
    58  		if _, ok := vu.Enums[val]; !ok {
    59  			values := make([]interface{}, 0)
    60  			for _, v := range vu.Enums {
    61  				values = append(values, v)
    62  			}
    63  
    64  			return &errors.NotInEnumError{
    65  				Target:  TargetUintValue,
    66  				Current: val,
    67  				Enums:   values,
    68  			}
    69  		}
    70  		return nil
    71  	}
    72  
    73  	if ((vu.ExclusiveMinimum && val == vu.Minimum) || val < vu.Minimum) ||
    74  		((vu.ExclusiveMaximum && val == vu.Maximum) || val > vu.Maximum) {
    75  		return &errors.OutOfRangeError{
    76  			Target:           TargetUintValue,
    77  			Current:          val,
    78  			Minimum:          vu.Minimum,
    79  			ExclusiveMinimum: vu.ExclusiveMinimum,
    80  			Maximum:          vu.Maximum,
    81  			ExclusiveMaximum: vu.ExclusiveMaximum,
    82  		}
    83  	}
    84  
    85  	if vu.MultipleOf != 0 {
    86  		if val%vu.MultipleOf != 0 {
    87  			return &errors.MultipleOfError{
    88  				Target:     TargetUintValue,
    89  				Current:    val,
    90  				MultipleOf: vu.MultipleOf,
    91  			}
    92  		}
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  func (Uint) New(ctx context.Context, r *Rule) (Validator, error) {
    99  	vu := &Uint{}
   100  
   101  	bits, err := UintRuleBitSize(r)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	vu.BitSize = uint(bits)
   106  
   107  	vu.ExclusiveMinimum = r.ExclusiveMin
   108  	vu.ExclusiveMaximum = r.ExclusiveMax
   109  
   110  	min, max, err := UintRuleRange(r, fmt.Sprintf("uint<%d>", vu.BitSize), vu.BitSize)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	vu.Minimum = min
   115  	if max != nil {
   116  		vu.Maximum = *max
   117  	}
   118  
   119  	vu.SetDefault()
   120  
   121  	multiple, enums, err := UintRuleValues(r, int(vu.BitSize))
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	vu.MultipleOf = multiple
   126  	vu.Enums = enums
   127  
   128  	return vu, vu.TypeCheck(r)
   129  }
   130  
   131  func (vu *Uint) TypeCheck(r *Rule) error {
   132  	switch r.Type.Kind() {
   133  	case reflect.Uint8:
   134  		if vu.BitSize > 8 {
   135  			return fmt.Errorf("bit size too large for type %s", r.String())
   136  		}
   137  		return nil
   138  	case reflect.Uint16:
   139  		if vu.BitSize > 16 {
   140  			return fmt.Errorf("bit size too large for type %s", r.String())
   141  		}
   142  		return nil
   143  	case reflect.Uint, reflect.Uint32:
   144  		if vu.BitSize > 32 {
   145  			return fmt.Errorf("bit size too large for type %s", r.String())
   146  		}
   147  		return nil
   148  	case reflect.Uint64:
   149  		return nil
   150  	}
   151  	return errors.NewUnsupportedTypeError(r.String(), vu.String())
   152  }
   153  
   154  func (vu *Uint) String() string {
   155  	r := rules.NewRule(vu.Names()[0])
   156  
   157  	r.Params = []rules.Node{
   158  		rules.NewLiteral([]byte(strconv.Itoa(int(vu.BitSize)))),
   159  	}
   160  
   161  	r.Range = []*rules.Lit{
   162  		rules.NewLiteral([]byte(fmt.Sprintf("%d", vu.Minimum))),
   163  		rules.NewLiteral([]byte(fmt.Sprintf("%d", vu.Maximum))),
   164  	}
   165  
   166  	r.ExclusiveMin = vu.ExclusiveMinimum
   167  	r.ExclusiveMax = vu.ExclusiveMaximum
   168  
   169  	if vu.MultipleOf != 0 {
   170  		r.ValueMatrix = [][]*rules.Lit{{
   171  			rules.NewLiteral([]byte("%" + fmt.Sprintf("%d", vu.MultipleOf))),
   172  		}}
   173  	} else if vu.Enums != nil {
   174  		ruleValues := make([]*rules.Lit, 0)
   175  		for _, e := range vu.Enums {
   176  			ruleValues = append(ruleValues, rules.NewLiteral([]byte(e)))
   177  		}
   178  		r.ValueMatrix = [][]*rules.Lit{ruleValues}
   179  	}
   180  
   181  	return string(r.Bytes())
   182  }