1package jose
2
3import "encoding/base64"
4
5// Encoder is satisfied if the type can marshal itself into a valid
6// structure for a JWS.
7type Encoder interface {
8	// Base64 implies T -> JSON -> RawURLEncodingBase64
9	Base64() ([]byte, error)
10}
11
12// Base64Decode decodes a base64-encoded byte slice.
13func Base64Decode(b []byte) ([]byte, error) {
14	buf := make([]byte, base64.RawURLEncoding.DecodedLen(len(b)))
15	n, err := base64.RawURLEncoding.Decode(buf, b)
16	return buf[:n], err
17}
18
19// Base64Encode encodes a byte slice.
20func Base64Encode(b []byte) []byte {
21	buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b)))
22	base64.RawURLEncoding.Encode(buf, b)
23	return buf
24}
25
26// EncodeEscape base64-encodes a byte slice but escapes it for JSON.
27// It'll return the format: `"base64"`
28func EncodeEscape(b []byte) []byte {
29	buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b))+2)
30	buf[0] = '"'
31	base64.RawURLEncoding.Encode(buf[1:], b)
32	buf[len(buf)-1] = '"'
33	return buf
34}
35
36// DecodeEscaped decodes a base64-encoded byte slice straight from a JSON
37// structure. It assumes it's in the format: `"base64"`, but can handle
38// cases where it's not.
39func DecodeEscaped(b []byte) ([]byte, error) {
40	if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' {
41		b = b[1 : len(b)-1]
42	}
43	return Base64Decode(b)
44}
45