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 }