-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
parameter.go
94 lines (86 loc) · 1.89 KB
/
parameter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package tl
import (
"fmt"
"strings"
)
// Parameter with Name and Type.
type Parameter struct {
// Name of Parameter.
Name string `json:"name,omitempty"`
// Type of Parameter.
Type Type `json:"type"`
// Flag specifies flag name and index if parameter is conditional.
Flag *Flag `json:"flag,omitempty"`
// Flags denotes whether Parameter is flags field (uint32).
//
// If true, Type and Flag are blank.
Flags bool `json:"flags,omitempty"`
// special case for {X:Type} definitions aka generic parameters,
// only "Name" field is populated.
typeDefinition bool
}
func (p Parameter) Conditional() bool {
return p.Flag != nil
}
func (p Parameter) String() string {
var b strings.Builder
if p.typeDefinition {
b.WriteRune('{')
}
if p.Name != "" {
// Anonymous parameter.
b.WriteString(p.Name)
b.WriteRune(':')
}
if p.typeDefinition {
b.WriteString("Type}")
return b.String()
}
if p.Flags {
b.WriteRune('#')
return b.String()
}
if p.Conditional() {
b.WriteString(p.Flag.String())
b.WriteRune('?')
}
b.WriteString(p.Type.String())
return b.String()
}
func (p *Parameter) Parse(s string) error {
if strings.HasPrefix(s, "{") {
if !strings.HasSuffix(s, ":Type}") {
return fmt.Errorf("unexpected generic %s", s)
}
p.typeDefinition = true
p.Name = strings.SplitN(s[1:], ":", 2)[0]
return nil
}
parts := strings.SplitN(s, ":", 2)
if len(parts) == 2 {
p.Name = parts[0]
s = parts[1]
} else {
// Anonymous parameter.
s = parts[0]
}
if s == "#" {
p.Flags = true
return nil
}
if pos := strings.Index(s, "?"); pos >= 0 {
p.Flag = &Flag{}
if err := p.Flag.Parse(s[:pos]); err != nil {
return fmt.Errorf("failed to parse flag: %w", err)
}
s = s[pos+1:]
}
if err := p.Type.Parse(s); err != nil {
return fmt.Errorf("failed to parse type: %w", err)
}
return nil
}
// Compile-time interface implementation assertion.
var (
_ fmt.Stringer = Parameter{}
)