aboutsummaryrefslogtreecommitdiff
path: root/ber/marshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'ber/marshal.go')
-rw-r--r--ber/marshal.go175
1 files changed, 90 insertions, 85 deletions
diff --git a/ber/marshal.go b/ber/marshal.go
index 6124197..041cb1b 100644
--- a/ber/marshal.go
+++ b/ber/marshal.go
@@ -1,110 +1,115 @@
package ber
-import (
- "bytes"
- "reflect"
-)
-
-type encodeState struct {
- bytes.Buffer
-}
-
-func Marshal(v interface{}) ([]byte, error) {
- e := &encodeState{}
- err := e.marshal(v)
- if err != nil {
- return nil, err
+func lenLen(i int) int {
+ n := 1
+ for ; i > 255; i >>= 8 {
+ n++
}
- return e.Bytes(), nil
-}
-
-func (e *encodeState) marshal(v interface{}) (err error) {
- e.reflectValue(reflect.ValueOf(v))
- return nil
-}
-
-func (e *encodeState) reflectValue(v reflect.Value) {
- valueEncoder(v)(e, v)
+ return n
}
-type encoderFunc func(e *encodeState, v reflect.Value)
-
-func valueEncoder(v reflect.Value) encoderFunc {
- if !v.IsValid() {
- return invalidValueEncoder
+func (s *state) marshalLen(val int) {
+ if val < 0x80 {
+ s.WriteByte(byte(val))
+ return
}
- 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
- case reflect.Struct:
- return structEncoder
- case reflect.Slice:
- return sliceEncoder
- default:
- return unsupportedTypeEncoder
+ n := lenLen(val)
+ s.WriteByte(byte(n) | 0x80)
+ for ; n > 0; n-- {
+ s.WriteByte(byte(val >> uint((n-1)*8)))
}
}
-type UnsupportedTypeError struct {
- Type reflect.Type
+func (s *state) marshalBool(val bool) {
+ s.marshalLen(1)
+ if val {
+ s.WriteByte(0xff)
+ } else {
+ s.WriteByte(0)
+ }
}
-func (e *UnsupportedTypeError) Error() string {
- return "BER: unsupported type: " + e.Type.String()
+func intLen(i int) int {
+ n := 1
+ for ; i > 127; i >>= 8 {
+ n++
+ }
+ for ; i < -128; i >>= 8 {
+ n++
+ }
+ return n
}
-func unsupportedTypeEncoder(e *encodeState, v reflect.Value) {
- e.error(&UnsupportedTypeError{v.Type()})
+func (s *state) marshalInt(val int) {
+ n := intLen(val)
+ s.marshalLen(n)
+ for ; n > 0; n-- {
+ s.WriteByte(byte(val >> uint((n-1)*8)))
+ }
}
-func (e *encodeState) error(err error) {
- panic(err)
+func (s *state) marshalString(val string) {
+ s.marshalLen(len(val))
+ s.Write([]byte(val))
}
-func intEncoder(e *encodeState, v reflect.Value) {
- b := MarshalInt(int(v.Int()))
- l := MarshalLen(len(b))
- t := MarshalClass(classUniversal, kindPrimitive, tagInteger)
- e.Write(t)
- e.Write(l)
- e.Write(b)
+func (s *state) marshalBase128(val int) {
+ if val == 0 {
+ s.WriteByte(0)
+ return
+ }
+ var l int
+ for i := val; i > 0; i >>= 7 {
+ l++
+ }
+ for i := l - 1; i >= 0; i-- {
+ o := byte(val >> uint(i*7) & 0x7f)
+ if i != 0 {
+ o |= 0x80
+ }
+ s.WriteByte(o)
+ }
}
-func objEncoder(e *encodeState, v reflect.Value) {
- b := MarshalOID(v.Interface().(OID))
- l := MarshalLen(len(b))
- t := MarshalClass(classUniversal, kindPrimitive, tagObjectIdentifier)
- e.Write(t)
- e.Write(l)
- e.Write(b)
+func (s *state) marshalOID(val OID) {
+ if len(val) < 2 || val[0] > 2 {
+ return
+ }
+ if val[0] < 2 && val[1] > 39 {
+ return
+ }
+ buf := &state{}
+ buf.marshalBase128(val[0]*40 + val[1])
+ for _, v := range val[2:] {
+ buf.marshalBase128(v)
+ }
+ s.marshalLen(buf.Len())
+ s.Write(buf.Bytes())
}
-func structEncoder(e *encodeState, v reflect.Value) {
- sube := &encodeState{}
- for i := 0; i < v.NumField(); i++ {
- sube.reflectValue(v.Field(i))
+func (s *state) marshalBitString(val BitString) {
+ pad := (8 - len(val)%8) % 8
+ l := len(val) / 8
+ if pad != 0 {
+ l++
}
- b := sube.Bytes()
- l := MarshalLen(len(b))
- t := MarshalClass(classUniversal, kindConstructed, tagSequence)
- e.Write(t)
- e.Write(l)
- e.Write(b)
+ b := make([]byte, l)
+ for i, v := range val {
+ if v {
+ x := i / 8
+ y := 7 - uint(i%8)
+ b[x] |= 1 << y
+ }
+ }
+ s.marshalLen(l + 1)
+ s.WriteByte(byte(pad))
+ s.Write(b)
}
-func sliceEncoder(e *encodeState, v reflect.Value) {
- if v.IsNil() {
- e.Write(MarshalClass(classUniversal, kindPrimitive, tagNull))
- e.Write([]byte{0})
- } else {
- e.Write(v.Bytes())
- }
+func (s *state) marshalClass(h Header) {
+ buf := &state{}
+ buf.marshalBase128(int(h.Tag))
+ b := buf.Bytes()
+ b[0] |= byte(h.Class) | byte(h.Kind)
+ s.Write(b)
}