pkg: adding base64 encoding for strings
cue's current implementation doesn't support encoding and decoding
of strings with base64. a new package `encoding/base64` adds
the missing funcionality as builtin's. go supports different
encoding methods for now only StdEncoding is supported in cue.
Issue #61
Change-Id: Ic656dee880c25f6b0a2a710e38b3ff86fb28ab8b
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2600
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/builtin_test.go b/cue/builtin_test.go
index b710f73..fd2a48d 100644
--- a/cue/builtin_test.go
+++ b/cue/builtin_test.go
@@ -56,6 +56,18 @@
test("math", `math.Floor("foo")`),
`_|_(cannot use "foo" (type string) as number in argument 1 to math.Floor)`,
}, {
+ test("encoding/base64", `base64.Encode(null, "foo")`),
+ `"Zm9v"`,
+ }, {
+ test("encoding/base64", `base64.Decode(null, base64.Encode(null, "foo"))`),
+ `'foo'`,
+ }, {
+ test("encoding/base64", `base64.Decode(null, "foo")`),
+ `_|_(error in call to encoding/base64.Decode: illegal base64 data at input byte 0)`,
+ }, {
+ test("encoding/base64", `base64.Decode({}, "foo")`),
+ `_|_(error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null)`,
+ }, {
test("encoding/hex", `hex.Encode("foo")`),
`"666f6f"`,
}, {
diff --git a/cue/builtins.go b/cue/builtins.go
index ca1e556..b7917a9 100644
--- a/cue/builtins.go
+++ b/cue/builtins.go
@@ -8,6 +8,7 @@
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
+ "encoding/base64"
"encoding/csv"
"encoding/hex"
"encoding/json"
@@ -185,6 +186,61 @@
},
}},
},
+ "encoding/base64": &builtinPkg{
+ native: []*builtin{{
+ Name: "EncodedLen",
+ Params: []kind{topKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ encoding, n := c.value(0), c.int(1)
+ c.ret, c.err = func() (interface{}, error) {
+ if err := encoding.Null(); err != nil {
+ return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.EncodedLen(n), nil
+ }()
+ },
+ }, {
+ Name: "DecodedLen",
+ Params: []kind{topKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ encoding, x := c.value(0), c.int(1)
+ c.ret, c.err = func() (interface{}, error) {
+ if err := encoding.Null(); err != nil {
+ return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.DecodedLen(x), nil
+ }()
+ },
+ }, {
+ Name: "Encode",
+ Params: []kind{topKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ encoding, src := c.value(0), c.bytes(1)
+ c.ret, c.err = func() (interface{}, error) {
+ if err := encoding.Null(); err != nil {
+ return "", fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.EncodeToString(src), nil
+ }()
+ },
+ }, {
+ Name: "Decode",
+ Params: []kind{topKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ encoding, s := c.value(0), c.string(1)
+ c.ret, c.err = func() (interface{}, error) {
+ if err := encoding.Null(); err != nil {
+ return nil, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.DecodeString(s)
+ }()
+ },
+ }},
+ },
"encoding/csv": &builtinPkg{
native: []*builtin{{
Name: "Encode",
diff --git a/pkg/encoding/base64/manual.go b/pkg/encoding/base64/manual.go
new file mode 100644
index 0000000..b292424
--- /dev/null
+++ b/pkg/encoding/base64/manual.go
@@ -0,0 +1,61 @@
+// Copyright 2019 The CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package base64 implements base64 encoding as specified by RFC 4648.
+package base64
+
+import (
+ "encoding/base64"
+ "fmt"
+
+ "cuelang.org/go/cue"
+)
+
+// EncodedLen returns the length in bytes of the base64 encoding
+// of an input buffer of length n. Encoding needs to be set to null
+// as only StdEncoding is supported for now.
+func EncodedLen(encoding cue.Value, n int) (int, error) {
+ if err := encoding.Null(); err != nil {
+ return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.EncodedLen(n), nil
+}
+
+// DecodedLen returns the maximum length in bytes of the decoded data
+// corresponding to n bytes of base64-encoded data. Encoding needs to be set to
+// null as only StdEncoding is supported for now.
+func DecodedLen(encoding cue.Value, x int) (int, error) {
+ if err := encoding.Null(); err != nil {
+ return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.DecodedLen(x), nil
+}
+
+// Encode returns the base64 encoding of src. Encoding needs to be set to null
+// as only StdEncoding is supported for now.
+func Encode(encoding cue.Value, src []byte) (string, error) {
+ if err := encoding.Null(); err != nil {
+ return "", fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.EncodeToString(src), nil
+}
+
+// Decode returns the bytes represented by the base64 string s. Encoding needs
+// to be set to null as only StdEncoding is supported for now.
+func Decode(encoding cue.Value, s string) ([]byte, error) {
+ if err := encoding.Null(); err != nil {
+ return nil, fmt.Errorf("base64: unsupported encoding: %v", err)
+ }
+ return base64.StdEncoding.DecodeString(s)
+}