github.com/sandwich-go/boost@v1.3.29/misc/annotation/registry.go (about)

     1  package annotation
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/sandwich-go/boost/xstrings"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  const all = "*"
    11  
    12  type resolver struct {
    13  	opts *Options
    14  }
    15  
    16  // New 创建一个解析器,默认使用 annotation@ 作为 MagicPrefix,只有包含 MagicPrefix 的行,才能萃取到注释
    17  // descriptors 可以指定萃取的注释名,以及是否为合法的注释
    18  // 若不指定 descriptors,则任意名的注释,均为合法的注释
    19  func New(opts ...Option) Resolver {
    20  	v := &resolver{opts: NewOptions(opts...)}
    21  	if len(v.opts.GetDescriptors()) == 0 {
    22  		v.opts.ApplyOption(WithDescriptors(Descriptor{Name: all}))
    23  	}
    24  	return v
    25  }
    26  
    27  var EmptyAnnotation = &annotation{}
    28  
    29  type annotation struct {
    30  	name       string
    31  	line       string
    32  	attributes map[string]string
    33  }
    34  
    35  func NewAnnotation(name string, attributes map[string]string) Annotation {
    36  	return &annotation{name: name, attributes: attributes}
    37  }
    38  
    39  func (a annotation) Name() string { return a.name }
    40  func (a annotation) Line() string { return a.line }
    41  func (a annotation) Contains(key string) bool {
    42  	_, ok := a.attributes[key]
    43  	return ok
    44  }
    45  
    46  func (a annotation) String(key string, defaultVal ...string) string {
    47  	v, ok := a.attributes[key]
    48  	if !ok {
    49  		return append(defaultVal, "")[0]
    50  	}
    51  	return xstrings.Trim(v)
    52  }
    53  
    54  func (a annotation) Int8(key string, defaultVal ...int8) (int8, error) {
    55  	val := a.String(key)
    56  	if len(val) == 0 {
    57  		return append(defaultVal, 0)[0], nil
    58  	}
    59  	iVal, err := strconv.ParseInt(val, 10, 8)
    60  	if err != nil {
    61  		return 0, err
    62  	}
    63  	return int8(iVal), nil
    64  }
    65  
    66  func (a annotation) Int16(key string, defaultVal ...int16) (int16, error) {
    67  	val := a.String(key)
    68  	if len(val) == 0 {
    69  		return append(defaultVal, 0)[0], nil
    70  	}
    71  	iVal, err := strconv.ParseInt(val, 10, 16)
    72  	if err != nil {
    73  		return 0, err
    74  	}
    75  	return int16(iVal), nil
    76  }
    77  
    78  func (a annotation) Int32(key string, defaultVal ...int32) (int32, error) {
    79  	val := a.String(key)
    80  	if len(val) == 0 {
    81  		return append(defaultVal, 0)[0], nil
    82  	}
    83  	iVal, err := strconv.ParseInt(val, 10, 32)
    84  	if err != nil {
    85  		return 0, err
    86  	}
    87  	return int32(iVal), nil
    88  }
    89  
    90  func (a annotation) Int64(key string, defaultVal ...int64) (int64, error) {
    91  	val := a.String(key)
    92  	if len(val) == 0 {
    93  		return append(defaultVal, 0)[0], nil
    94  	}
    95  	return strconv.ParseInt(val, 10, 64)
    96  }
    97  
    98  func (a annotation) Uint8(key string, defaultVal ...uint8) (uint8, error) {
    99  	val := a.String(key)
   100  	if len(val) == 0 {
   101  		return append(defaultVal, 0)[0], nil
   102  	}
   103  	iVal, err := strconv.ParseUint(val, 10, 8)
   104  	if err != nil {
   105  		return 0, err
   106  	}
   107  	return uint8(iVal), nil
   108  }
   109  
   110  func (a annotation) Uint16(key string, defaultVal ...uint16) (uint16, error) {
   111  	val := a.String(key)
   112  	if len(val) == 0 {
   113  		return append(defaultVal, 0)[0], nil
   114  	}
   115  	iVal, err := strconv.ParseUint(val, 10, 16)
   116  	if err != nil {
   117  		return 0, err
   118  	}
   119  	return uint16(iVal), nil
   120  }
   121  
   122  func (a annotation) Uint32(key string, defaultVal ...uint32) (uint32, error) {
   123  	val := a.String(key)
   124  	if len(val) == 0 {
   125  		return append(defaultVal, 0)[0], nil
   126  	}
   127  	iVal, err := strconv.ParseUint(val, 10, 32)
   128  	if err != nil {
   129  		return 0, err
   130  	}
   131  	return uint32(iVal), nil
   132  }
   133  
   134  func (a annotation) Uint64(key string, defaultVal ...uint64) (uint64, error) {
   135  	val := a.String(key)
   136  	if len(val) == 0 {
   137  		return append(defaultVal, 0)[0], nil
   138  	}
   139  	return strconv.ParseUint(val, 10, 64)
   140  }
   141  
   142  func (a annotation) Int(key string, defaultVal ...int) (int, error) {
   143  	val := a.String(key)
   144  	if len(val) == 0 {
   145  		return append(defaultVal, 0)[0], nil
   146  	}
   147  	iVal, err := strconv.ParseInt(val, 10, 32)
   148  	if err != nil {
   149  		return 0, err
   150  	}
   151  	return int(iVal), nil
   152  }
   153  
   154  func (a annotation) Float32(key string, defaultVal ...float32) (float32, error) {
   155  	val := a.String(key)
   156  	if len(val) == 0 {
   157  		return append(defaultVal, 0)[0], nil
   158  	}
   159  	iVal, err := strconv.ParseFloat(val, 32)
   160  	if err != nil {
   161  		return 0, err
   162  	}
   163  	return float32(iVal), nil
   164  }
   165  
   166  func (a annotation) Float64(key string, defaultVal ...float64) (float64, error) {
   167  	val := a.String(key)
   168  	if len(val) == 0 {
   169  		return append(defaultVal, 0)[0], nil
   170  	}
   171  	return strconv.ParseFloat(val, 64)
   172  }
   173  
   174  func (a annotation) Bool(key string, defaultVal ...bool) (bool, error) {
   175  	val := a.String(key)
   176  	if len(val) == 0 {
   177  		return append(defaultVal, false)[0], nil
   178  	}
   179  	return xstrings.IsTrue(xstrings.Trim(strings.ToLower(val))), nil
   180  }
   181  
   182  func (desc Descriptor) match(ann Annotation) bool {
   183  	if desc.Name != all && ann.Name() != desc.Name {
   184  		return false
   185  	}
   186  	if desc.Validator != nil {
   187  		return desc.Validator(ann)
   188  	}
   189  	return true
   190  }
   191  
   192  func (r *resolver) Resolve(line string) (Annotation, error) {
   193  	line = strings.TrimSpace(line)
   194  	for _, desc := range r.opts.GetDescriptors() {
   195  		if !strings.Contains(line, r.opts.GetMagicPrefix()) {
   196  			continue
   197  		}
   198  		ann, err := parser(line, r.opts.GetLowerKey())
   199  		if err != nil {
   200  			return nil, err
   201  		}
   202  		if !desc.match(ann) {
   203  			continue
   204  		}
   205  		return ann, nil
   206  	}
   207  	return nil, ErrNoAnnotation
   208  }
   209  
   210  func (r *resolver) ResolveMany(lines ...string) ([]Annotation, error) {
   211  	as := make([]Annotation, 0, len(lines))
   212  	for _, line := range lines {
   213  		if ann, err := r.Resolve(line); err == nil {
   214  			as = append(as, ann)
   215  		} else if err != ErrNoAnnotation {
   216  			return nil, err
   217  		}
   218  	}
   219  	return as, nil
   220  }
   221  
   222  func (r *resolver) ResolveWithName(name string, lines ...string) (Annotation, error) {
   223  	for _, line := range lines {
   224  		if ann, err := r.Resolve(line); err == nil && ann.Name() == name {
   225  			return ann, nil
   226  		} else if err != nil && err != ErrNoAnnotation {
   227  			return nil, err
   228  		}
   229  	}
   230  	return nil, ErrNoAnnotation
   231  }
   232  
   233  func (r *resolver) ResolveNoDuplicate(lines ...string) ([]Annotation, error) {
   234  	as, err := r.ResolveMany(lines...)
   235  	if err != nil || len(as) <= 1 {
   236  		return as, err
   237  	}
   238  	mapping := make(map[string]Annotation)
   239  	for _, v := range as {
   240  		if v1, ok := mapping[v.Name()]; ok {
   241  			return nil, fmt.Errorf("got duplicate annotation name with name: %s line1: %s line2: %s", v.Name(), v.Line(), v1.Line())
   242  		}
   243  		mapping[v.Name()] = v
   244  	}
   245  	return as, nil
   246  }