diff --git a/bees/placeholders.go b/bees/placeholders.go index 1f99cc6a..2f0644e4 100644 --- a/bees/placeholders.go +++ b/bees/placeholders.go @@ -22,8 +22,10 @@ package bees import ( + "bytes" "errors" "fmt" + "io/ioutil" "net/url" "reflect" "strconv" @@ -227,6 +229,80 @@ func ConvertValue(v interface{}, dst interface{}) error { panic(fmt.Sprintf("Unhandled type %+v for url.Values conversion", reflect.TypeOf(vt))) } + case *BinaryValue: + switch vt := v.(type) { + case *BinaryValue: + d = vt + case []byte: + if d != nil { + d.MimeType = "unknwown" + d.Data = ioutil.NopCloser(bytes.NewBuffer(vt)) + } else { + *d = BinaryValue{ + MimeType: "unknown", + Data: ioutil.NopCloser(bytes.NewBuffer(vt)), + } + } + + default: + panic(fmt.Sprintf("Unhandled type %+v for *BinaryValue conversion", reflect.TypeOf(vt))) + } + + case *[]*BinaryValue: + switch vt := v.(type) { + case []*BinaryValue: + d = &vt + case *[]*BinaryValue: + d = vt + case [][]byte: + bvs := make([]*BinaryValue, len(vt)) + for i, b := range vt { + bvs[i] = &BinaryValue{ + MimeType: "unknown", + Data: ioutil.NopCloser(bytes.NewBuffer(b)), + } + } + *d = bvs + default: + panic(fmt.Sprintf("Unhandled type %+v for []*BinaryValue conversion", reflect.TypeOf(vt))) + } + + case *[]byte: + switch vt := v.(type) { + case []byte: + *d = vt + case *[]byte: + d = vt + case *BinaryValue: + b, err := ioutil.ReadAll(vt.Data) + if err != nil { + panic(fmt.Sprintf("Unhandled error during type conversion for []byte from *BinaryValue: %s", err)) + } + *d = b + default: + panic(fmt.Sprintf("Unhandled type %+v for []byte conversion", reflect.TypeOf(vt))) + } + + case *[][]byte: + switch vt := v.(type) { + case [][]byte: + d = &vt + case *[][]byte: + d = vt + case []*BinaryValue: + bb := make([][]byte, len(vt)) + for _, bv := range vt { + b, err := ioutil.ReadAll(bv.Data) + if err != nil { + panic(fmt.Sprintf("Unhandled error during type conversion for [][]byte from []*BinaryValue: %s", err)) + } + bb = append(bb, b) + } + d = &bb + default: + panic(fmt.Sprintf("Unhandled type %+v for [][]byte conversion", reflect.TypeOf(vt))) + } + default: panic(fmt.Sprintf("Unhandled dst type %+v", reflect.TypeOf(dst))) } diff --git a/bees/placeholders_test.go b/bees/placeholders_test.go new file mode 100644 index 00000000..fc7c539a --- /dev/null +++ b/bees/placeholders_test.go @@ -0,0 +1,77 @@ +package bees + +import ( + "bytes" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBinaryConversions(t *testing.T) { + testCases := []struct { + dst interface{} + v interface{} + name string + assert func(t *testing.T, v interface{}, dst interface{}) + }{ + { + name: "Test conversion from BinaryValue to []byte", + dst: &[]byte{}, + v: &BinaryValue{Data: ioutil.NopCloser(bytes.NewBuffer([]byte{0x00, 0x01, 0xFF}))}, + assert: func(t *testing.T, v interface{}, dst interface{}) { + b, ok := dst.(*[]byte) + require.True(t, ok) + assert.Len(t, *b, 3) + }, + }, + + { + name: "Test conversion from []byte to *BinaryValue", + dst: &BinaryValue{}, + v: []byte{0x00, 0x01, 0xFF}, + assert: func(t *testing.T, v interface{}, dst interface{}) { + b, ok := dst.(*BinaryValue) + require.True(t, ok) + require.NotNil(t, b.Data) + bb, _ := ioutil.ReadAll(b.Data) + assert.Len(t, bb, 3) + }, + }, + + { + name: "Test conversion from [][]byte to *[]*BinaryValue", + dst: &[]*BinaryValue{}, + v: [][]byte{{0x00}, {0x01}, {0x02}}, + assert: func(t *testing.T, v interface{}, dst interface{}) { + b, ok := dst.(*[]*BinaryValue) + require.True(t, ok) + + require.Len(t, *b, 3) + for _, bv := range *b { + bb, _ := ioutil.ReadAll(bv.Data) + assert.Len(t, bb, 1) + } + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + if err, ok := r.(error); ok { + t.Fatalf("Failed to convert values: %s", err) + } else { + t.Fatalf("Failed to convert values: unknown reason") + } + } + }() + ConvertValue(tc.v, tc.dst) + if tc.assert != nil { + tc.assert(t, tc.v, tc.dst) + } + }) + } +} diff --git a/bees/types.go b/bees/types.go new file mode 100644 index 00000000..b55d5605 --- /dev/null +++ b/bees/types.go @@ -0,0 +1,8 @@ +package bees + +import "io" + +type BinaryValue struct { + MimeType string + Data io.ReadCloser +} diff --git a/go.mod b/go.mod index ceb911ea..0eaa54d1 100644 --- a/go.mod +++ b/go.mod @@ -92,6 +92,7 @@ require ( github.com/sromku/go-gitter v0.0.0-20170828210750-70f7030a94a6 github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/stretchr/objx v0.2.0 // indirect + github.com/stretchr/testify v1.4.0 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 // indirect golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734