1package base64
2
3import (
4	"bytes"
5	"encoding/base64"
6	"encoding/binary"
7
8	"github.com/pkg/errors"
9)
10
11func Encode(src []byte) []byte {
12	enc := base64.RawURLEncoding
13	dst := make([]byte, enc.EncodedLen(len(src)))
14	enc.Encode(dst, src)
15	return dst
16}
17
18func EncodeToStringStd(src []byte) string {
19	return base64.StdEncoding.EncodeToString(src)
20}
21
22func EncodeToString(src []byte) string {
23	return base64.RawURLEncoding.EncodeToString(src)
24}
25
26func EncodeUint64ToString(v uint64) string {
27	data := make([]byte, 8)
28	binary.BigEndian.PutUint64(data, v)
29
30	i := 0
31	for ; i < len(data); i++ {
32		if data[i] != 0x0 {
33			break
34		}
35	}
36
37	return EncodeToString(data[i:])
38}
39
40func Decode(src []byte) ([]byte, error) {
41	var enc *base64.Encoding
42
43	var isRaw = !bytes.HasSuffix(src, []byte{'='})
44	var isURL = !bytes.ContainsAny(src, "+/")
45	switch {
46	case isRaw && isURL:
47		enc = base64.RawURLEncoding
48	case isURL:
49		enc = base64.URLEncoding
50	case isRaw:
51		enc = base64.RawStdEncoding
52	default:
53		enc = base64.StdEncoding
54	}
55
56	dst := make([]byte, enc.DecodedLen(len(src)))
57	n, err := enc.Decode(dst, src)
58	if err != nil {
59		return nil, errors.Wrap(err, `failed to decode source`)
60	}
61	return dst[:n], nil
62}
63
64func DecodeString(src string) ([]byte, error) {
65	return Decode([]byte(src))
66}
67