github.com/oam-dev/kubevela@v1.9.11/references/cuegen/tag.go (about)

     1  /*
     2  Copyright 2023 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cuegen
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  )
    23  
    24  type tagOptions struct {
    25  	// basic
    26  	Name     string
    27  	Inline   bool
    28  	Optional bool
    29  
    30  	// extended
    31  	Default *string // nil means no default value
    32  	Enum    []string
    33  }
    34  
    35  // TODO(iyear): be customizable
    36  const (
    37  	basicTag = "json" // same as json tag
    38  	extTag   = "cue"  // format: cue:"key1:value1;key2:value2;boolValue1;boolValue2"
    39  )
    40  
    41  func (g *Generator) parseTag(tag string) *tagOptions {
    42  	if tag == "" {
    43  		return &tagOptions{}
    44  	}
    45  
    46  	name, opts := parseTag(reflect.StructTag(tag).Get(basicTag))
    47  	ext := parseExtTag(reflect.StructTag(tag).Get(extTag))
    48  
    49  	return &tagOptions{
    50  		Name:     name,
    51  		Inline:   opts.Has("inline"),
    52  		Optional: opts.Has("omitempty"),
    53  
    54  		Default: ext.GetX("default"),
    55  		Enum:    unescapeSplit(ext.Get("enum"), ","),
    56  	}
    57  }
    58  
    59  type basicTagOptions string
    60  
    61  func parseTag(tag string) (string, basicTagOptions) {
    62  	tag, opt, _ := strings.Cut(tag, ",")
    63  	return tag, basicTagOptions(opt)
    64  }
    65  
    66  func (o basicTagOptions) Has(opt string) bool {
    67  	if len(o) == 0 {
    68  		return false
    69  	}
    70  	s := string(o)
    71  	for s != "" {
    72  		var name string
    73  		name, s, _ = strings.Cut(s, ",")
    74  		if name == opt {
    75  			return true
    76  		}
    77  	}
    78  	return false
    79  }
    80  
    81  func parseExtTag(str string) extTagOptions {
    82  	settings := map[string]string{}
    83  	if str == "" {
    84  		return settings
    85  	}
    86  
    87  	pairs := unescapeSplit(str, ";")
    88  	for _, pair := range pairs {
    89  		switch kv := unescapeSplit(pair, ":"); len(kv) {
    90  		case 1:
    91  			settings[kv[0]] = ""
    92  		case 2:
    93  			settings[kv[0]] = kv[1]
    94  		default:
    95  			// ignore invalid pair
    96  		}
    97  	}
    98  
    99  	return settings
   100  }
   101  
   102  func unescapeSplit(str string, sep string) []string {
   103  	if str == "" {
   104  		return []string{}
   105  	}
   106  
   107  	ss := strings.Split(str, sep)
   108  	for i := 0; i < len(ss); i++ {
   109  		j := i
   110  		if len(ss[j]) > 0 {
   111  			for {
   112  				if ss[j][len(ss[j])-1] == '\\' && i+1 < len(ss) {
   113  					i++
   114  					ss[j] = ss[j][0:len(ss[j])-1] + sep + ss[i]
   115  					ss[i] = ""
   116  				} else {
   117  					break
   118  				}
   119  			}
   120  		}
   121  	}
   122  
   123  	// filter empty strings
   124  	res := make([]string, 0, len(ss))
   125  	for _, s := range ss {
   126  		if s != "" {
   127  			res = append(res, s)
   128  		}
   129  	}
   130  	return res
   131  }
   132  
   133  type extTagOptions map[string]string
   134  
   135  // GetX returns the value of the key if it exists, otherwise nil.
   136  func (e extTagOptions) GetX(key string) *string {
   137  	if v, ok := e[key]; ok {
   138  		return &v
   139  	}
   140  	return nil
   141  }
   142  
   143  // Get returns the value of the key if it exists, otherwise "".
   144  func (e extTagOptions) Get(key string) string {
   145  	return e[key]
   146  }