Stdlib encodings: hex, base64 (#216) (#221)

* stdlib/hex and stdlib/base64

* stdlib/hex and stdlib/base64: added docs
This commit is contained in:
Ma_124 2019-08-09 19:36:45 +02:00 committed by Jacob R. McCollum
parent 2e74690f5e
commit 1ee7425c9d
9 changed files with 146 additions and 1 deletions

16
docs/stdlib-base64.md Normal file
View file

@ -0,0 +1,16 @@
# Module - "base64"
```golang
fmt := import("base64")
```
## Functions
- `encode(src)`: returns the base64 encoding of src.
- `decode(s)`: returns the bytes represented by the base64 string s.
- `raw_encode(src)`: returns the base64 encoding of src but omits the padding.
- `raw_decode(s)`: returns the bytes represented by the base64 string s which omits the padding.
- `url_encode(src)`: returns the url-base64 encoding of src.
- `url_decode(s)`: returns the bytes represented by the url-base64 string s.
- `raw_url_encode(src)`: returns the url-base64 encoding of src but omits the padding.
- `raw_url_decode(s)`: returns the bytes represented by the url-base64 string s which omits the padding.

10
docs/stdlib-hex.md Normal file
View file

@ -0,0 +1,10 @@
# Module - "hex"
```golang
fmt := import("hex")
```
## Functions
- `encode(src)`: returns the hexadecimal encoding of src.
- `decode(s)`: returns the bytes represented by the hexadecimal string s.

View file

@ -8,3 +8,5 @@
- [fmt](https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md): formatting functions
- [json](https://github.com/d5/tengo/blob/master/docs/stdlib-json.md): JSON functions
- [enum](https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md): Enumeration functions
- [hex](https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md): hex encoding and decoding functions
- [base64](https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md): base64 encoding and decoding functions

20
stdlib/base64.go Normal file
View file

@ -0,0 +1,20 @@
package stdlib
import (
"encoding/base64"
"github.com/d5/tengo/objects"
)
var base64Module = map[string]objects.Object{
"encode": &objects.UserFunction{Value: FuncAYRS(base64.StdEncoding.EncodeToString)},
"decode": &objects.UserFunction{Value: FuncASRYE(base64.StdEncoding.DecodeString)},
"raw_encode": &objects.UserFunction{Value: FuncAYRS(base64.RawStdEncoding.EncodeToString)},
"raw_decode": &objects.UserFunction{Value: FuncASRYE(base64.RawStdEncoding.DecodeString)},
"url_encode": &objects.UserFunction{Value: FuncAYRS(base64.URLEncoding.EncodeToString)},
"url_decode": &objects.UserFunction{Value: FuncASRYE(base64.URLEncoding.DecodeString)},
"raw_url_encode": &objects.UserFunction{Value: FuncAYRS(base64.RawURLEncoding.EncodeToString)},
"raw_url_decode": &objects.UserFunction{Value: FuncASRYE(base64.RawURLEncoding.DecodeString)},
}

20
stdlib/base64_test.go Normal file
View file

@ -0,0 +1,20 @@
package stdlib_test
import "testing"
var base64Bytes1 = []byte{0x06, 0xAC, 0x76, 0x1B, 0x1D, 0x6A, 0xFA, 0x9D, 0xB1, 0xA0}
const base64Std = "Bqx2Gx1q+p2xoA=="
const base64URL = "Bqx2Gx1q-p2xoA=="
const base64RawStd = "Bqx2Gx1q+p2xoA"
const base64RawURL = "Bqx2Gx1q-p2xoA"
func TestBase64(t *testing.T) {
module(t, `base64`).call("encode", base64Bytes1).expect(base64Std)
module(t, `base64`).call("decode", base64Std).expect(base64Bytes1)
module(t, `base64`).call("url_encode", base64Bytes1).expect(base64URL)
module(t, `base64`).call("url_decode", base64URL).expect(base64Bytes1)
module(t, `base64`).call("raw_encode", base64Bytes1).expect(base64RawStd)
module(t, `base64`).call("raw_decode", base64RawStd).expect(base64Bytes1)
module(t, `base64`).call("raw_url_encode", base64Bytes1).expect(base64RawURL)
module(t, `base64`).call("raw_url_decode", base64RawURL).expect(base64Bytes1)
}

View file

@ -11,4 +11,6 @@ var BuiltinModules = map[string]map[string]objects.Object{
"rand": randModule,
"fmt": fmtModule,
"json": jsonModule,
"base64": base64Module,
"hex": hexModule,
}

View file

@ -1036,6 +1036,29 @@ func FuncAYRIE(fn func([]byte) (int, error)) objects.CallableFunc {
}
}
// FuncAYRS transform a function of 'func([]byte) string' signature
// into CallableFunc type.
func FuncAYRS(fn func([]byte) string) objects.CallableFunc {
return func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
y1, ok := objects.ToByteSlice(args[0])
if !ok {
return nil, objects.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes(compatible)",
Found: args[0].TypeName(),
}
}
res := fn(y1)
return &objects.String{Value: res}, nil
}
}
// FuncASRIE transform a function of 'func(string) (int, error)' signature
// into CallableFunc type.
func FuncASRIE(fn func(string) (int, error)) objects.CallableFunc {
@ -1062,6 +1085,36 @@ func FuncASRIE(fn func(string) (int, error)) objects.CallableFunc {
}
}
// FuncASRYE transform a function of 'func(string) ([]byte, error)' signature
// into CallableFunc type.
func FuncASRYE(fn func(string) ([]byte, error)) objects.CallableFunc {
return func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
s1, ok := objects.ToString(args[0])
if !ok {
return nil, objects.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
}
}
res, err := fn(s1)
if err != nil {
return wrapError(err), nil
}
if len(res) > tengo.MaxBytesLen {
return nil, objects.ErrBytesLimit
}
return &objects.Bytes{Value: res}, nil
}
}
// FuncAIRSsE transform a function of 'func(int) ([]string, error)' signature
// into CallableFunc type.
func FuncAIRSsE(fn func(int) ([]string, error)) objects.CallableFunc {

11
stdlib/hex.go Normal file
View file

@ -0,0 +1,11 @@
package stdlib
import (
"encoding/hex"
"github.com/d5/tengo/objects"
)
var hexModule = map[string]objects.Object{
"encode": &objects.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
"decode": &objects.UserFunction{Value: FuncASRYE(hex.DecodeString)},
}

11
stdlib/hex_test.go Normal file
View file

@ -0,0 +1,11 @@
package stdlib_test
import "testing"
var hexBytes1 = []byte{0x06, 0xAC, 0x76, 0x1B, 0x1D, 0x6A, 0xFA, 0x9D, 0xB1, 0xA0}
const hex1 = "06ac761b1d6afa9db1a0"
func TestHex(t *testing.T) {
module(t, `hex`).call("encode", hexBytes1).expect(hex1)
module(t, `hex`).call("decode", hex1).expect(hexBytes1)
}