1package pgs 2 3import ( 4 "fmt" 5 "sort" 6 "strconv" 7 "strings" 8 "time" 9) 10 11const outputPathKey = "output_path" 12 13// Parameters provides a convenience for accessing and modifying the parameters 14// passed into the protoc-gen-star plugin. 15type Parameters map[string]string 16 17// ParseParameters converts the raw params string provided by protoc into a 18// representative mapping. 19func ParseParameters(p string) (params Parameters) { 20 parts := strings.Split(p, ",") 21 params = make(map[string]string, len(parts)) 22 23 for _, p = range parts { 24 if i := strings.Index(p, "="); i < 0 { 25 params[p] = "" 26 } else { 27 params[p[:i]] = p[i+1:] 28 } 29 } 30 31 return 32} 33 34// Clone creates an independent copy of Parameters p. 35func (p Parameters) Clone() Parameters { 36 out := make(Parameters, len(p)) 37 for k, v := range p { 38 out[k] = v 39 } 40 return out 41} 42 43// OutputPath returns the protoc-gen-star special parameter. If not set in the 44// execution of protoc, "." is returned, indicating that output is relative to 45// the (unknown) output location for sub-plugins or the directory where protoc 46// is executed for a Module. Setting "output_path" during the protoc execution 47// ensures that Modules can know absolutely where to generate code. 48func (p Parameters) OutputPath() string { return p.StrDefault(outputPathKey, ".") } 49 50// SetOutputPath sets the protoc-gen-star OutputPath parameter. This is useful 51// for overriding the behavior of the ImportPath at runtime. 52func (p Parameters) SetOutputPath(path string) { p.SetStr(outputPathKey, path) } 53 54// String satisfies the string.Stringer interface. This method returns p in the 55// format it is provided to the protoc execution. Output of this function is 56// always stable; parameters are sorted before the string is emitted. 57func (p Parameters) String() string { 58 parts := make([]string, 0, len(p)) 59 60 for k, v := range p { 61 if v == "" { 62 parts = append(parts, k) 63 } else { 64 parts = append(parts, fmt.Sprintf("%s=%s", k, v)) 65 } 66 } 67 68 sort.Strings(parts) 69 70 return strings.Join(parts, ",") 71} 72 73// Str returns the parameter with name, returning an empty string if it is not 74// set. 75func (p Parameters) Str(name string) string { return p.StrDefault(name, "") } 76 77// StrDefault returns the parameter with name, or if it is unset, returns the 78// def default value. 79func (p Parameters) StrDefault(name string, def string) string { 80 if s, ok := p[name]; ok { 81 return s 82 } 83 84 return def 85} 86 87// SetStr sets the parameter name to s. 88func (p Parameters) SetStr(name string, s string) { p[name] = s } 89 90// Int returns the parameter with name, returning zero if it is not set. An 91// error is returned if the value cannot be parsed as an int. 92func (p Parameters) Int(name string) (int, error) { return p.IntDefault(name, 0) } 93 94// IntDefault returns the parameter with name, or if it is unset, returns the 95// def default value. An error is returned if the value cannot be parsed as an 96// int. 97func (p Parameters) IntDefault(name string, def int) (int, error) { 98 if s, ok := p[name]; ok { 99 return strconv.Atoi(s) 100 } 101 return def, nil 102} 103 104// SetInt sets the parameter name to i. 105func (p Parameters) SetInt(name string, i int) { p[name] = strconv.Itoa(i) } 106 107// Uint returns the parameter with name, returning zero if it is not set. An 108// error is returned if the value cannot be parsed as a base-10 uint. 109func (p Parameters) Uint(name string) (uint, error) { return p.UintDefault(name, 0) } 110 111// UintDefault returns the parameter with name, or if it is unset, returns the 112// def default value. An error is returned if the value cannot be parsed as a 113// base-10 uint. 114func (p Parameters) UintDefault(name string, def uint) (uint, error) { 115 if s, ok := p[name]; ok { 116 ui, err := strconv.ParseUint(s, 10, strconv.IntSize) 117 return uint(ui), err 118 } 119 return def, nil 120} 121 122// SetUint sets the parameter name to ui. 123func (p Parameters) SetUint(name string, ui uint) { p[name] = strconv.FormatUint(uint64(ui), 10) } 124 125// Float returns the parameter with name, returning zero if it is 126// not set. An error is returned if the value cannot be parsed as a float64 127func (p Parameters) Float(name string) (float64, error) { return p.FloatDefault(name, 0) } 128 129// FloatDefault returns the parameter with name, or if it is unset, returns the 130// def default value. An error is returned if the value cannot be parsed as a 131// float64. 132func (p Parameters) FloatDefault(name string, def float64) (float64, error) { 133 if s, ok := p[name]; ok { 134 return strconv.ParseFloat(s, 64) 135 } 136 return def, nil 137} 138 139// SetFloat sets the parameter name to f. 140func (p Parameters) SetFloat(name string, f float64) { p[name] = strconv.FormatFloat(f, 'g', -1, 64) } 141 142// Bool returns the parameter with name, returning false if it is not set. An 143// error is returned if the value cannot be parsed as a boolean. Empty values 144// are considered true. 145func (p Parameters) Bool(name string) (bool, error) { return p.BoolDefault(name, false) } 146 147// BoolDefault returns the parameter with name, or if it is unset, returns the 148// def default value. An error is returned if the value cannot be parsed as a 149// boolean. Empty values are considered true. 150func (p Parameters) BoolDefault(name string, def bool) (bool, error) { 151 if s, ok := p[name]; ok { 152 if strings.TrimSpace(s) == "" { 153 return true, nil 154 } 155 return strconv.ParseBool(s) 156 } 157 158 return def, nil 159} 160 161// SetBool sets the parameter name to b. 162func (p Parameters) SetBool(name string, b bool) { p[name] = strconv.FormatBool(b) } 163 164// Duration returns the parameter with name, returning zero if it is not set. 165// An error is returned if the value cannot be parsed as a time.Duration. 166func (p Parameters) Duration(name string) (time.Duration, error) { return p.DurationDefault(name, 0) } 167 168// DurationDefault returns the parameter with name, or if it is unset, returns 169// the def default value. An error is returned if the value cannot be parsed as 170// a time.Duration. 171func (p Parameters) DurationDefault(name string, def time.Duration) (time.Duration, error) { 172 if s, ok := p[name]; ok { 173 return time.ParseDuration(s) 174 } 175 return def, nil 176} 177 178// SetDuration sets the parameter name to d. 179func (p Parameters) SetDuration(name string, d time.Duration) { p[name] = d.String() } 180