aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-06-27 01:34:48 +0200
committerDimitri Sokolyuk <demon@dim13.org>2015-06-27 01:34:48 +0200
commit6b6c369b624b9ddccd9a23eed78e0340db99ad85 (patch)
treee29a0467e2321f6cbfb1994a6339d709839b3212
parent69bf3fb4d2017639d5b0b01c1a5ba6e2dd31274f (diff)
Add Marshal
-rw-r--r--ber/int.go15
-rw-r--r--ber/int_test.go2
-rw-r--r--ber/marshal.go82
-rw-r--r--ber/marshal_test.go12
4 files changed, 106 insertions, 5 deletions
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)
+}