From 6b6c369b624b9ddccd9a23eed78e0340db99ad85 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 27 Jun 2015 01:34:48 +0200 Subject: Add Marshal --- ber/int.go | 15 +++++++--- ber/int_test.go | 2 +- ber/marshal.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ber/marshal_test.go | 12 ++++++++ 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 ber/marshal.go create mode 100644 ber/marshal_test.go diff --git a/ber/int.go b/ber/int.go index 32cc9af..97fd7b8 100644 --- a/ber/int.go +++ b/ber/int.go @@ -1,6 +1,8 @@ package ber -func intLen(i int) int { +import "reflect" + +func intLen(i int64) int { n := 1 for i > 255 { n++ @@ -13,7 +15,7 @@ func intLen(i int) int { return n } -func unmarshalInt(b []byte) (i int) { +func unmarshalInt(b []byte) (i int64) { nn := len(b) neg := b[0]&0x80 != 0 if b[0] == 0xFF { @@ -24,7 +26,7 @@ func unmarshalInt(b []byte) (i int) { if neg { v = ^v } - i += int(v) << uint((nn-n-1)*8) + i += int64(v) << uint((nn-n-1)*8) } if neg { i = -i - 1 @@ -32,7 +34,7 @@ func unmarshalInt(b []byte) (i int) { return } -func marshalInt(i int) (b []byte) { +func marshalInt(i int64) (b []byte) { for n := intLen(i); n > 0; n-- { b = append(b, byte(i>>uint((n-1)*8))) } @@ -44,3 +46,8 @@ func marshalInt(i int) (b []byte) { } return } + +func intEncoder(e *encodeState, v reflect.Value) { + b := marshalInt(v.Int()) + e.Write(b) +} diff --git a/ber/int_test.go b/ber/int_test.go index 03139c1..9a015c5 100644 --- a/ber/int_test.go +++ b/ber/int_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func testInt(t *testing.T, i int, b []byte) { +func testInt(t *testing.T, i int64, b []byte) { a := marshalInt(i) if !bytes.Equal(a, b) { t.Error("BER", i, "expected", b, "got", a) diff --git a/ber/marshal.go b/ber/marshal.go new file mode 100644 index 0000000..ca91271 --- /dev/null +++ b/ber/marshal.go @@ -0,0 +1,82 @@ +package ber + +import ( + "bytes" + "reflect" + "runtime" +) + +type encodeState struct { + bytes.Buffer +} + +type Marshaler interface { + MarschalBER() ([]byte, error) +} + +func Marshal(v interface{}) ([]byte, error) { + e := &encodeState{} + err := e.marshal(v) + if err != nil { + return nil, err + } + return e.Bytes(), nil +} + +func (e *encodeState) marshal(v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + if s, ok := r.(string); ok { + panic(s) + } + err = r.(error) + } + }() + e.reflectValue(reflect.ValueOf(v)) + return nil +} + +func (e *encodeState) reflectValue(v reflect.Value) { + valueEncoder(v)(e, v) +} + +type encoderFunc func(e *encodeState, v reflect.Value) + +func valueEncoder(v reflect.Value) encoderFunc { + if !v.IsValid() { + return invalidValueEncoder + } + return newTypeEncoder(v.Type()) +} + +func invalidValueEncoder(e *encodeState, v reflect.Value) { + e.WriteByte(0) +} + +func newTypeEncoder(t reflect.Type) encoderFunc { + switch t.Kind() { + case reflect.Int: + return intEncoder + default: + return unsupportedTypeEncoder + } +} + +type UnsupportedTypeError struct { + Type reflect.Type +} + +func (e *UnsupportedTypeError) Error() string { + return "BER: unsupported type: " + e.Type.String() +} + +func unsupportedTypeEncoder(e *encodeState, v reflect.Value) { + e.error(&UnsupportedTypeError{v.Type()}) +} + +func (e *encodeState) error(err error) { + panic(err) +} diff --git a/ber/marshal_test.go b/ber/marshal_test.go new file mode 100644 index 0000000..da568ed --- /dev/null +++ b/ber/marshal_test.go @@ -0,0 +1,12 @@ +package ber + +import "testing" + +func TestMarschal(t *testing.T) { + i := 42 + b, err := Marshal(i) + if err != nil { + t.Error(err) + } + t.Log(b) +} -- cgit v1.2.3