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

     1  package validator
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strconv"
     7  	"unicode"
     8  
     9  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/errors"
    10  	"github.com/machinefi/w3bstream/pkg/depends/x/ptrx"
    11  )
    12  
    13  func MaxUint(bits uint) uint64 { return 1<<bits - 1 }
    14  
    15  func UintRuleBitSize(r *Rule) (bits uint64, err error) {
    16  	buf := &bytes.Buffer{}
    17  
    18  	for _, char := range r.Name {
    19  		if unicode.IsDigit(char) {
    20  			buf.WriteRune(char)
    21  		}
    22  	}
    23  
    24  	if buf.Len() == 0 && r.Params != nil {
    25  		if len(r.Params) != 1 {
    26  			err = fmt.Errorf(
    27  				"unit should only 1 parameter, but got %d", len(r.Params),
    28  			)
    29  			return
    30  		}
    31  		buf.Write(r.Params[0].Bytes())
    32  	}
    33  
    34  	if buf.Len() != 0 {
    35  		s := buf.String()
    36  		bits, err = strconv.ParseUint(s, 10, 8)
    37  		if err != nil || bits > 64 {
    38  			err = errors.NewSyntaxError(
    39  				"unit parameter should be valid bit size, but got `%s`", s,
    40  			)
    41  			return
    42  		}
    43  	}
    44  
    45  	if bits == 0 {
    46  		bits = 32
    47  	}
    48  	return
    49  }
    50  
    51  func UintRuleRange(r *Rule, typ string, bits uint) (uint64, *uint64, error) {
    52  	if r.Range == nil {
    53  		return 0, nil, nil
    54  	}
    55  
    56  	if r.Name == "array" && len(r.Range) > 1 {
    57  		return 0, nil, errors.NewSyntaxError("array should declare length only")
    58  	}
    59  
    60  	parseUint := func(b []byte) (*uint64, error) {
    61  		if len(b) == 0 {
    62  			return nil, nil
    63  		}
    64  		n, err := strconv.ParseUint(string(b), 10, int(bits))
    65  		if err != nil {
    66  			return nil, fmt.Errorf(" %s value is not correct: %s", typ, err)
    67  		}
    68  		return &n, nil
    69  	}
    70  
    71  	ranges := r.Range
    72  	switch len(ranges) {
    73  	case 2:
    74  		min, err := parseUint(ranges[0].Bytes())
    75  		if err != nil {
    76  			return 0, nil, fmt.Errorf("min %s", err)
    77  		}
    78  		if min == nil {
    79  			min = ptrx.Uint64(0)
    80  		}
    81  
    82  		max, err := parseUint(ranges[1].Bytes())
    83  		if err != nil {
    84  			return 0, nil, fmt.Errorf("max %s", err)
    85  		}
    86  
    87  		if max != nil && *max < *min {
    88  			return 0, nil, fmt.Errorf(
    89  				"max %s value must be equal or large than min value %d, current %d",
    90  				typ, min, max,
    91  			)
    92  		}
    93  
    94  		return *min, max, nil
    95  	case 1:
    96  		min, err := parseUint(ranges[0].Bytes())
    97  		if err != nil {
    98  			return 0, nil, fmt.Errorf("min %s", err)
    99  		}
   100  		if min == nil {
   101  			min = ptrx.Uint64(0)
   102  		}
   103  		return *min, min, nil
   104  	}
   105  	return 0, nil, nil
   106  }
   107  
   108  func UintRuleValues(r *Rule, bits int) (multiple uint64, enums map[uint64]string, err error) {
   109  	values := r.ComputedValues()
   110  	if values == nil {
   111  		return
   112  	}
   113  
   114  	if len(values) == 1 {
   115  		raw := values[0].Bytes()
   116  		if raw[0] == '%' {
   117  			raw = raw[1:]
   118  			multiple, err = strconv.ParseUint(string(raw), 10, bits)
   119  			if err != nil {
   120  				err = errors.NewSyntaxError(
   121  					"multipleOf should be a valid int%d value, but got `%s`",
   122  					bits, raw,
   123  				)
   124  				return
   125  			}
   126  		}
   127  	}
   128  
   129  	if multiple == 0 {
   130  		enums = map[uint64]string{}
   131  		for _, v := range values {
   132  			s := string(v.Bytes())
   133  			enumv, _err := strconv.ParseUint(s, 10, bits)
   134  			if _err != nil {
   135  				err = errors.NewSyntaxError(
   136  					"enum should be a valid int%d value, but got `%s`", bits, v,
   137  				)
   138  				return
   139  			}
   140  			enums[enumv] = s
   141  		}
   142  	}
   143  	return
   144  }