From 54caa4e7e085e177ff05b719ae247d21fe8c257e Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 26 Sep 2015 12:04:34 +0200 Subject: Replace with new implementation --- ber/marshal.go | 175 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 90 insertions(+), 85 deletions(-) (limited to 'ber/marshal.go') 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) } -- cgit v1.2.3