-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
bareitem.go
102 lines (95 loc) · 2.26 KB
/
bareitem.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
package httpsfv
import (
"errors"
"fmt"
"reflect"
"strings"
)
// ErrInvalidBareItem is returned when a bare item is invalid.
var ErrInvalidBareItem = errors.New(
"invalid bare item type (allowed types are bool, string, int64, float64, []byte and Token)",
)
// assertBareItem asserts that v is a valid bare item
// according to https://httpwg.org/specs/rfc8941.html#item.
//
// v can be either:
//
// * an integer (Section 3.3.1.)
// * a decimal (Section 3.3.2.)
// * a string (Section 3.3.3.)
// * a token (Section 3.3.4.)
// * a byte sequence (Section 3.3.5.)
// * a boolean (Section 3.3.6.)
func assertBareItem(v interface{}) {
switch v.(type) {
case bool,
string,
int,
int8,
int16,
int32,
int64,
uint,
uint8,
uint16,
uint32,
uint64,
float32,
float64,
[]byte,
Token:
return
default:
panic(fmt.Errorf("%w: got %s", ErrInvalidBareItem, reflect.TypeOf(v)))
}
}
// marshalBareItem serializes as defined in
// https://httpwg.org/specs/rfc8941.html#ser-bare-item.
func marshalBareItem(b *strings.Builder, v interface{}) error {
switch v := v.(type) {
case bool:
return marshalBoolean(b, v)
case string:
return marshalString(b, v)
case int64:
return marshalInteger(b, v)
case int, int8, int16, int32:
return marshalInteger(b, reflect.ValueOf(v).Int())
case uint, uint8, uint16, uint32, uint64:
// Casting an uint64 to an int64 is possible because the maximum allowed value is 999,999,999,999,999
return marshalInteger(b, int64(reflect.ValueOf(v).Uint()))
case float32, float64:
return marshalDecimal(b, v.(float64))
case []byte:
return marshalBinary(b, v)
case Token:
return v.marshalSFV(b)
default:
panic(ErrInvalidBareItem)
}
}
// parseBareItem parses as defined in
// https://httpwg.org/specs/rfc8941.html#parse-bare-item.
func parseBareItem(s *scanner) (interface{}, error) {
if s.eof() {
return nil, &UnmarshalError{s.off, ErrUnexpectedEndOfString}
}
c := s.data[s.off]
switch c {
case '"':
return parseString(s)
case '?':
return parseBoolean(s)
case '*':
return parseToken(s)
case ':':
return parseBinary(s)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return parseNumber(s)
default:
if isAlpha(c) {
return parseToken(s)
}
return nil, &UnmarshalError{s.off, ErrUnrecognizedCharacter}
}
}