-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathparams.go
143 lines (111 loc) · 2.7 KB
/
params.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package httpsfv
import (
"errors"
"strings"
)
// Params are an ordered map of key-value pairs that are associated with an item or an inner list.
//
// See https://httpwg.org/specs/rfc8941.html#param.
type Params struct {
names []string
values map[string]interface{}
}
// ErrInvalidParameterFormat is returned when the format of a parameter is invalid.
var ErrInvalidParameterFormat = errors.New("invalid parameter format")
// ErrInvalidParameterValue is returned when a parameter key is invalid.
var ErrInvalidParameterValue = errors.New("invalid parameter value")
// ErrMissingParameters is returned when the Params structure is missing from the element.
var ErrMissingParameters = errors.New("missing parameters")
// NewParams creates a new ordered map.
func NewParams() *Params {
p := Params{}
p.names = []string{}
p.values = map[string]interface{}{}
return &p
}
// Get retrieves a parameter.
func (p *Params) Get(k string) (interface{}, bool) {
v, ok := p.values[k]
return v, ok
}
// Add appends a new parameter to the ordered list.
// If the key already exists, overwrite its value.
func (p *Params) Add(k string, v interface{}) {
assertBareItem(v)
if _, exists := p.values[k]; !exists {
p.names = append(p.names, k)
}
p.values[k] = v
}
// Del removes a parameter from the ordered list.
func (p *Params) Del(key string) bool {
if _, ok := p.values[key]; !ok {
return false
}
for i, k := range p.names {
if k == key {
p.names = append(p.names[:i], p.names[i+1:]...)
break
}
}
delete(p.values, key)
return true
}
// Names retrieves the list of parameter names in the appropriate order.
func (p *Params) Names() []string {
return p.names
}
// marshalSFV serializes as defined in
// https://httpwg.org/specs/rfc8941.html#ser-params.
func (p *Params) marshalSFV(b *strings.Builder) error {
if p == nil {
return ErrMissingParameters
}
for _, k := range p.names {
if err := b.WriteByte(';'); err != nil {
return err
}
if err := marshalKey(b, k); err != nil {
return err
}
v := p.values[k]
if v == true {
continue
}
if err := b.WriteByte('='); err != nil {
return err
}
if err := marshalBareItem(b, v); err != nil {
return err
}
}
return nil
}
// parseParams parses as defined in
// https://httpwg.org/specs/rfc8941.html#parse-param.
func parseParams(s *scanner) (*Params, error) {
p := NewParams()
for !s.eof() {
if s.data[s.off] != ';' {
break
}
s.off++
s.scanWhileSp()
k, err := parseKey(s)
if err != nil {
return nil, err
}
var i interface{}
if !s.eof() && s.data[s.off] == '=' {
s.off++
i, err = parseBareItem(s)
if err != nil {
return nil, err
}
} else {
i = true
}
p.Add(k, i)
}
return p, nil
}