github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/validator/rules/rule.go (about) 1 package rules 2 3 import ( 4 "bytes" 5 "regexp" 6 ) 7 8 type Node interface { 9 node() // node flag only 10 Bytes() []byte 11 } 12 13 type Lit struct { 14 Raw []byte 15 Node 16 } 17 18 func NewLiteral(raw []byte) *Lit { return &Lit{Raw: raw} } 19 20 func (l *Lit) Append(bytes []byte) { l.Raw = append(l.Raw, bytes...) } 21 22 func (l *Lit) Bytes() []byte { 23 if l == nil { 24 return nil 25 } 26 return l.Raw 27 } 28 29 type Rule struct { 30 RAW []byte 31 Name string 32 Params []Node 33 Range []*Lit 34 35 ExclusiveMin bool 36 ExclusiveMax bool 37 ValueMatrix [][]*Lit 38 Pattern *regexp.Regexp 39 40 Optional bool 41 DftValue []byte 42 43 Node 44 } 45 46 func NewRule(name string) *Rule { return &Rule{Name: name} } 47 48 func Parse(rule string) (*Rule, error) { return ParseRaw([]byte(rule)) } 49 50 func ParseRaw(b []byte) (*Rule, error) { return NewScanner(b).RootRule() } 51 52 func (r *Rule) ComputedValues() []*Lit { 53 return ComputedValueMatrix(r.ValueMatrix) 54 } 55 56 func ComputedValueMatrix(matrix [][]*Lit) []*Lit { 57 switch len(matrix) { 58 case 0: 59 return nil 60 case 1: 61 return matrix[0] 62 default: 63 ri, li := matrix[0], len(matrix) 64 rj, lj := matrix[1], len(matrix) 65 values := make([]*Lit, li*lj) 66 for i := range ri { 67 for j := range rj { 68 raw := append(append([]byte{}, ri[i].Bytes()...), rj[j].Bytes()...) 69 values[i*lj+j] = NewLiteral(raw) 70 } 71 } 72 return ComputedValueMatrix(append([][]*Lit{values}, matrix[2:]...)) 73 } 74 } 75 76 func (r *Rule) Bytes() []byte { 77 if r == nil { 78 return nil 79 } 80 81 buf := &bytes.Buffer{} 82 buf.WriteByte('@') 83 buf.WriteString(r.Name) 84 85 if len(r.Params) > 0 { 86 buf.WriteByte('<') 87 for i, p := range r.Params { 88 if i > 0 { 89 buf.WriteByte(',') 90 } 91 if p != nil { 92 buf.Write(p.Bytes()) 93 } 94 } 95 buf.WriteByte('>') 96 } 97 98 if len(r.Range) > 0 { 99 if r.ExclusiveMin { 100 buf.WriteRune('(') 101 } else { 102 buf.WriteRune('[') 103 } 104 for i, p := range r.Range { 105 if i > 0 { 106 buf.WriteByte(',') 107 } 108 buf.Write(p.Bytes()) 109 } 110 if r.ExclusiveMax { 111 buf.WriteRune(')') 112 } else { 113 buf.WriteRune(']') 114 } 115 } 116 117 for i := range r.ValueMatrix { 118 values := r.ValueMatrix[i] 119 120 buf.WriteByte('{') 121 122 for i, p := range values { 123 if i > 0 { 124 buf.WriteByte(',') 125 } 126 buf.Write(p.Bytes()) 127 } 128 129 buf.WriteByte('}') 130 } 131 132 if r.Pattern != nil { 133 buf.Write(Slash([]byte(r.Pattern.String()))) 134 } 135 136 if r.Optional { 137 if r.DftValue != nil { 138 buf.WriteByte(' ') 139 buf.WriteByte('=') 140 buf.WriteByte(' ') 141 142 buf.Write(SingleQuote(r.DftValue)) 143 } else { 144 buf.WriteByte('?') 145 } 146 } 147 148 return buf.Bytes() 149 }