Skip to content

Commit

Permalink
Add gzip codec (#200)
Browse files Browse the repository at this point in the history
  • Loading branch information
myzie committed Mar 9, 2024
1 parent 21602e4 commit 297643d
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
36 changes: 36 additions & 0 deletions builtins/codecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package builtins

import (
"bytes"
"compress/gzip"
"context"
"encoding/base32"
"encoding/base64"
"encoding/csv"
"encoding/hex"
"encoding/json"
"errors"
"io"
"net/url"
"sort"
"sync"
Expand Down Expand Up @@ -37,6 +39,7 @@ func init() {
RegisterCodec("yaml", &Codec{Encode: encodeYAML, Decode: decodeYAML})
RegisterCodec("csv", &Codec{Encode: encodeCsv, Decode: decodeCsv})
RegisterCodec("urlquery", &Codec{Encode: encodeUrlQuery, Decode: decodeUrlQuery})
RegisterCodec("gzip", &Codec{Encode: encodeGzip, Decode: decodeGzip})
}

// RegisterCodec registers a new codec
Expand Down Expand Up @@ -78,6 +81,22 @@ func Encode(ctx context.Context, args ...object.Object) object.Object {
return codec.Encode(ctx, args[0])
}

func encodeGzip(ctx context.Context, obj object.Object) object.Object {
data, err := object.AsBytes(obj)
if err != nil {
return err
}
var buf bytes.Buffer
writer := gzip.NewWriter(&buf)
if _, err := writer.Write(data); err != nil {
return object.NewError(err)
}
if err := writer.Close(); err != nil {
return object.NewError(err)
}
return object.NewByteSlice(buf.Bytes())
}

func encodeBase64(ctx context.Context, obj object.Object) object.Object {
data, err := object.AsBytes(obj)
if err != nil {
Expand Down Expand Up @@ -231,6 +250,23 @@ func Decode(ctx context.Context, args ...object.Object) object.Object {
return codec.Decode(ctx, args[0])
}

func decodeGzip(ctx context.Context, obj object.Object) object.Object {
data, errObj := object.AsBytes(obj)
if errObj != nil {
return errObj
}
reader := bytes.NewReader(data)
gzreader, err := gzip.NewReader(reader)
if err != nil {
return object.NewError(err)
}
output, err := io.ReadAll(gzreader)
if err != nil {
return object.NewError(err)
}
return object.NewByteSlice(output)
}

func decodeBase64(ctx context.Context, obj object.Object) object.Object {
data, err := object.AsBytes(obj)
if err != nil {
Expand Down
57 changes: 57 additions & 0 deletions builtins/codecs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package builtins

import (
"context"
"testing"

"github.com/risor-io/risor/object"
"github.com/stretchr/testify/require"
)

func TestBinaryCodecs(t *testing.T) {
codecs := []string{
"base64",
"base32",
"hex",
"gzip",
}
ctx := context.Background()
value := "Farfalle"
for _, codec := range codecs {
codecName := object.NewString(codec)
t.Run(codec, func(t *testing.T) {
encoded := Encode(ctx, object.NewString(value), codecName)
if errObj, ok := encoded.(*object.Error); ok {
t.Fatalf("encoding error: %v", errObj)
}
decoded := Decode(ctx, encoded, codecName)
if errObj, ok := decoded.(*object.Error); ok {
t.Fatalf("decoding error: %v", errObj)
}
require.Equal(t, object.NewByteSlice([]byte(value)), decoded)
})
}
}

func TestUnknownCodec(t *testing.T) {
ctx := context.Background()
encoded := Encode(ctx, object.NewString("oops"), object.NewString("unknown"))
errObj, ok := encoded.(*object.Error)
require.True(t, ok)
require.Equal(t, "codec not found: unknown", errObj.Value().Error())
}

func TestJsonCodec(t *testing.T) {
ctx := context.Background()
value := "thumbs up 👍🏼"
encoded := Encode(ctx, object.NewString(value), object.NewString("json"))
if errObj, ok := encoded.(*object.Error); ok {
t.Fatalf("encoding error: %v", errObj)
}
require.Equal(t, object.NewString("\""+value+"\""), encoded)
decoded := Decode(ctx, encoded, object.NewString("json"))
if errObj, ok := decoded.(*object.Error); ok {
t.Fatalf("decoding error: %v", errObj)
}
require.Equal(t, object.NewString(value), decoded)
}

0 comments on commit 297643d

Please sign in to comment.