-
Notifications
You must be signed in to change notification settings - Fork 0
/
base64.go
135 lines (114 loc) · 3.31 KB
/
base64.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
package cbor
import (
"encoding/base64"
"encoding/hex"
"encoding/json"
)
var b64 = base64.StdEncoding.Strict()
var b64url = base64.RawURLEncoding.Strict()
type encMode int
const (
encModeBase64 encMode = iota
encModeBase64URL
encModeBase16
)
func (enc encMode) Encode(data []byte) string {
switch enc {
case encModeBase64:
return b64.EncodeToString(data)
case encModeBase64URL:
return b64url.EncodeToString(data)
case encModeBase16:
return hex.EncodeToString(data)
}
return ""
}
type b64ctx struct {
mode encMode
}
func (ctx b64ctx) Convert(data any) any {
switch data := data.(type) {
case []byte:
return ctx.mode.Encode(data)
case map[string]any:
ret := make(map[string]any, len(data))
for k, v := range data {
ret[k] = ctx.Convert(v)
}
return ret
case []any:
ret := make([]any, len(data))
for i, v := range data {
ret[i] = ctx.Convert(v)
}
return ret
case ExpectedBase64URL:
orig := ctx.mode
ctx.mode = encModeBase64URL
ret := ctx.Convert(data.Content)
ctx.mode = orig
return ret
case ExpectedBase64:
orig := ctx.mode
ctx.mode = encModeBase64
ret := ctx.Convert(data.Content)
ctx.mode = orig
return ret
case ExpectedBase16:
orig := ctx.mode
ctx.mode = encModeBase16
ret := ctx.Convert(data.Content)
ctx.mode = orig
return ret
}
return data
}
var _ json.Marshaler = ExpectedBase64URL{}
var _ json.Marshaler = ExpectedBase64{}
var _ json.Marshaler = ExpectedBase16{}
// ExpectedBase64URL is data expected to be encoded as base64url-encoding.
// CBOR tags that has tag number 21 is converted to this type.
// When encoded to JSON, []byte in Content is converted to a base64url-encoded string.
// See RFC 8949 Section 3.4.5.2.
type ExpectedBase64URL struct {
Content any
}
func (e ExpectedBase64URL) MarshalJSON() ([]byte, error) {
ctx := &b64ctx{mode: encModeBase64URL}
data := ctx.Convert(e.Content)
return json.Marshal(data)
}
// ExpectedBase64 is data expected to be encoded as base64-encoding.
// CBOR tags that has tag number 22 is converted to this type.
// When encoded to JSON, []byte in Content is converted to a base64-encoded string.
// See RFC 8949 Section 3.4.5.2.
type ExpectedBase64 struct {
Content any
}
func (e ExpectedBase64) MarshalJSON() ([]byte, error) {
ctx := &b64ctx{mode: encModeBase64}
data := ctx.Convert(e.Content)
return json.Marshal(data)
}
// ExpectedBase16 is data expected to be encoded as base16-encoding (as known as hex-encoding).
// CBOR tags that has tag number 23 is converted to this type.
// When encoded to JSON, []byte in Content is converted to a base16-encoded string.
// See RFC 8949 Section 3.4.5.2.
type ExpectedBase16 struct {
Content any
}
func (e ExpectedBase16) MarshalJSON() ([]byte, error) {
ctx := &b64ctx{mode: encModeBase16}
data := ctx.Convert(e.Content)
return json.Marshal(data)
}
// Base64String is a base64 with padding encoded data.
// CBOR tags that has tag number 34 is converted to this type.
// The decoder and the encoder validate that it is a valid base64-encoded string.
// See RFC 8949 Section 3.4.5.3.
type Base64String string
// Base64URLString is a base64url with no padding encoded string.
// CBOR tags that has tag number 33 is converted to this type.
// The decoder and the encoder validate that it is a valid base64url-encoded string.
// See RFC 8949 Section 3.4.5.3.
type Base64URLString string