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  }