-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathb64.go
109 lines (97 loc) · 3.04 KB
/
b64.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
package tree
import (
"encoding/base64"
"fmt"
"strings"
"github.com/cyphrme/coze"
)
// SB64 is useful for B64 map keys. Idiomatically, map key type should be `B64`,
// but currently in Go map keys are only type `string`, not `[]byte`. Since
// B64's underlying type is `[]byte` it cannot be used as a map key. See
// https://github.com/golang/go/issues/283 and
// https://github.com/google/go-cmp/issues/67. SB64 will be deprecated if/when
// Go supports []byte keys.
//
// This is an acceptable hack because (from https://go.dev/blog/strings)
//
// >[A] string holds arbitrary bytes. It is not required to hold Unicode text,
// > UTF-8 text, or any other predefined format. As far as the content of a
// > string is concerned, it is exactly equivalent to a slice of bytes.
type SB64 string
// String implements fmt.Stringer
func (b SB64) String() string {
return coze.B64(b).String()
}
// GoString implements fmt.GoString
func (b SB64) GoString() string {
return b.String()
}
// UnmarshalJSON implements json.Unmarshaler.
func (t *SB64) UnmarshalJSON(b []byte) error {
// JSON.Unmarshal returns b encapsulated in quotes which is invalid base64 characters.
bb, err := base64.URLEncoding.Strict().WithPadding(base64.NoPadding).DecodeString(strings.Trim(string(b), "\""))
if err != nil {
return err
}
b64 := coze.B64(bb)
*t = SB64(b64.String())
return nil
}
// B64Map is for maps with B64 as keys. See notes on SB64. Without this,
// defining struct values as `map[SB64][]B64` will undesirably print map keys as
// []byte and not B64 since json.Marshal looks for the key's primitive type if a
// defined custom type for the top level struct type is not present.
type B64Map map[SB64][]coze.B64
// MarshalJSON implements json.Marshaler.
func (t B64Map) MarshalJSON() ([]byte, error) {
i := 0
l := len(t)
s := "{"
for k, v := range t {
i++
vj, err := coze.Marshal(v)
if err != nil {
return nil, err
}
s += `"` + fmt.Sprint(k) + `":` + string(vj)
if i != l {
s += ","
}
}
return []byte(s + "}"), nil
}
// TODO
// func (t B64Map) UnmarshalJSON(b []byte) error {
// fmt.Println(b)
// // JSON.Unmarshal returns b encapsulated in quotes which is invalid base64 characters.
// s, err := base64.URLEncoding.Strict().WithPadding(base64.NoPadding).DecodeString(strings.Trim(string(b), "\""))
// if err != nil {
// return err
// }
// *t = B64(s)
// return nil
// }
// B64Map is for maps with B64 as keys. See notes on SB64. Without this,
// defining struct values as `map[tree.SB64][]coze.B64` will undesirably print
// map keys as []byte and not B64 since json.Marshal looks for the key's
// primitive type if a defined custom type for the top level struct type is not
// present.
type B64MapP map[SB64]*[]coze.B64
// MarshalJSON implements json.Marshaler.
func (t B64MapP) MarshalJSON() ([]byte, error) {
var s = "{"
var i = 0
var l = len(t)
for k, v := range t {
i++
vj, err := coze.Marshal(v)
if err != nil {
return nil, err
}
s += "\"" + fmt.Sprint(k) + "\":" + string(vj)
if i != l {
s += ","
}
}
return []byte(s + "}"), nil
}