/
token.go
70 lines (57 loc) · 1.52 KB
/
token.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
package data
import (
"crypto/rand"
"database/sql/driver"
"encoding/base64"
"errors"
)
var (
invalidTokenError = errors.New("invalid token")
tokenEncoding = base64.URLEncoding.WithPadding(base64.NoPadding)
)
type Token []byte
func NewToken(length int) (Token, error) {
t := make([]byte, length)
if _, err := rand.Read(t); err != nil {
return nil, err
}
return t, nil
}
// UnmarshalBinary sets the value of the Token based on a slice of bytes.
func (t *Token) UnmarshalBinary(data []byte) error {
*t = make([]byte, len(data))
copy(*t, data)
return nil
}
// MarshalText returns a base64-encoded slice of bytes.
func (t Token) MarshalText() (text []byte, err error) {
data := make([]byte, tokenEncoding.EncodedLen(len(t)))
base64.URLEncoding.Encode(data, t)
return data, nil
}
// UnmarshalText sets the value of the Token based on a base64-encoded slice of bytes.
func (t *Token) UnmarshalText(text []byte) error {
data := make([]byte, tokenEncoding.DecodedLen(len(text)))
n, err := tokenEncoding.Decode(data, text)
if err != nil {
return err
}
*t = data[:n]
return nil
}
// String returns a base64-encoded string.
func (t Token) String() string {
return tokenEncoding.EncodeToString(t)
}
// Scan sets the value of the Token based on an interface.
func (id *Token) Scan(src interface{}) error {
data, ok := src.([]byte)
if !ok {
return invalidTokenError
}
return id.UnmarshalBinary(data)
}
// Value implements the driver Valuer interface.
func (t Token) Value() (driver.Value, error) {
return []byte(t), nil
}