aboutsummaryrefslogtreecommitdiff
path: root/ber
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-09-26 12:04:34 +0200
committerDimitri Sokolyuk <demon@dim13.org>2015-09-26 12:04:34 +0200
commit54caa4e7e085e177ff05b719ae247d21fe8c257e (patch)
tree363400fe1c6c1e7b696c72caaabc4882756355fa /ber
parent1fcefc99a82bac6ce725b6f11277e4aa291a7f51 (diff)
Replace with new implementation
Diffstat (limited to 'ber')
-rw-r--r--ber/base128.go31
-rw-r--r--ber/base128_test.go26
-rw-r--r--ber/ber_test.go (renamed from ber/new/ber_test.go)0
-rw-r--r--ber/bitstring.go93
-rw-r--r--ber/bitstring_test.go73
-rw-r--r--ber/bool.go16
-rw-r--r--ber/bool_test.go32
-rw-r--r--ber/class.go31
-rw-r--r--ber/class_test.go36
-rw-r--r--ber/common.go (renamed from ber/new/common.go)0
-rw-r--r--ber/dump.go66
-rw-r--r--ber/encode.go118
-rw-r--r--ber/int.go33
-rw-r--r--ber/int_test.go36
-rw-r--r--ber/len.go50
-rw-r--r--ber/len_test.go34
-rw-r--r--ber/marshal.go175
-rw-r--r--ber/marshal_test.go11
-rw-r--r--ber/new/class.go135
-rw-r--r--ber/new/dump.go40
-rw-r--r--ber/new/marshal.go107
-rw-r--r--ber/obj.go65
-rw-r--r--ber/obj_test.go37
-rw-r--r--ber/packet.go15
-rw-r--r--ber/string.go9
-rw-r--r--ber/string_test.go30
-rw-r--r--ber/unmarshal.go (renamed from ber/new/unmarshal.go)13
27 files changed, 262 insertions, 1050 deletions
diff --git a/ber/base128.go b/ber/base128.go
deleted file mode 100644
index 6f94f35..0000000
--- a/ber/base128.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package ber
-
-import "io"
-
-func base128(n int) (b []byte) {
- if n == 0 {
- return []byte{0}
- }
- l := 0
- for i := n; i > 0; i >>= 7 {
- l++
- }
- for i := l - 1; i >= 0; i-- {
- o := byte(n>>uint(i*7)) & 0x7f
- if i != 0 {
- o |= 0x80
- }
- b = append(b, o)
- }
- return
-}
-
-func Debase128(r io.ByteReader) (i int) {
- for {
- b, _ := r.ReadByte()
- i = (i << 7) | int(b&0x7f)
- if b&0x80 == 0 {
- return
- }
- }
-}
diff --git a/ber/base128_test.go b/ber/base128_test.go
deleted file mode 100644
index c06bca3..0000000
--- a/ber/base128_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type base128Test struct {
- in int
- out []byte
-}
-
-var base128TestData = []base128Test{
- {643, []byte{0x85, 0x03}},
- {113549, []byte{0x86, 0xF7, 0x0D}},
- {49152, []byte{0x83, 0x80, 0x00}},
-}
-
-func TestBase128(t *testing.T) {
- for _, test := range base128TestData {
- n := base128(test.in)
- if !bytes.Equal(n, test.out) {
- t.Error(test.in, "expected", test.out, "got", n)
- }
- }
-}
diff --git a/ber/new/ber_test.go b/ber/ber_test.go
index 8365987..8365987 100644
--- a/ber/new/ber_test.go
+++ b/ber/ber_test.go
diff --git a/ber/bitstring.go b/ber/bitstring.go
deleted file mode 100644
index eabc354..0000000
--- a/ber/bitstring.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package ber
-
-// BitString
-type BitString []bool
-
-func UnmarshalBitString(b []byte) (bs BitString) {
- padding := int(b[0])
- length := (len(b)-1)*8 - padding
- for i := 0; i < length; i++ {
- x := 1 + i/8
- y := 7 - uint(i%8)
- bit := b[x]&(1<<y) != 0
- bs = append(bs, bit)
- }
- return
-}
-
-func MarshalBitString(bs BitString) (b []byte) {
- padding := (8 - len(bs)%8) % 8
- length := len(bs) / 8
- if padding != 0 {
- length++
- }
- b = make([]byte, length+1)
- b[0] = byte(padding)
- for i, bi := range bs {
- x := 1 + i/8
- y := 7 - uint(i%8)
- if bi {
- b[x] |= 1 << y
- }
- }
- return
-}
-
-func (bs BitString) String() (s string) {
- bmap := map[bool]string{
- true: "1",
- false: "0",
- }
- for i, bit := range bs {
- if i > 0 && i%4 == 0 {
- s += " "
- }
- s += bmap[bit]
- }
- return
-}
-
-func (bs BitString) IsSet(n int) bool {
- if n > len(bs) {
- return false
- }
- return bs[n]
-}
-
-func pow2(n int) int {
- i := 1
- for i < n+1 {
- i <<= 1
- }
- return i
-}
-
-func (bs *BitString) Set(n int) {
- if len(*bs) < n {
- nbs := make(BitString, pow2(n))
- copy(nbs, *bs)
- *bs = nbs
- }
- (*bs)[n] = true
-}
-
-func (bs *BitString) Clear(n int) {
- if len(*bs) < n {
- nbs := make(BitString, pow2(n))
- copy(nbs, *bs)
- *bs = nbs
- }
- (*bs)[n] = false
-}
-
-func (bs BitString) Equal(s BitString) bool {
- if len(bs) != len(s) {
- return false
- }
- for i := 0; i < len(bs); i++ {
- if bs[i] != s[i] {
- return false
- }
- }
- return true
-}
diff --git a/ber/bitstring_test.go b/ber/bitstring_test.go
deleted file mode 100644
index 3c67228..0000000
--- a/ber/bitstring_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type bitTest struct {
- bytes []byte
- bits BitString
-}
-
-var bitTestData = []bitTest{
- {
- []byte{0, 8, 0},
- BitString{
- false, false, false, false, true, false, false, false,
- false, false, false, false, false, false, false, false,
- },
- },
- {
- []byte{7, 0x80},
- BitString{true},
- },
- {
- []byte{4, 0x20},
- BitString{false, false, true, false},
- },
-}
-
-func bitsEqual(a, b BitString) bool {
- if len(a) != len(b) {
- return false
- }
- for i := range a {
- if a[i] != b[i] {
- return false
- }
- }
- return true
-}
-
-func TestBitString(t *testing.T) {
- for _, test := range bitTestData {
- bi := UnmarshalBitString(test.bytes)
- if !bitsEqual(bi, test.bits) {
- t.Error(test.bytes, "expexted", test.bits, "got", bi)
- }
- by := MarshalBitString(test.bits)
- if !bytes.Equal(by, test.bytes) {
- t.Error(test.bits, "expexted", test.bytes, "got", by)
- }
- }
-}
-
-func TestSet(t *testing.T) {
- bs := BitString{true, false}
- bs.Set(4)
- ex := BitString{true, false, false, false, true, false, false, false}
- if !bs.Equal(ex) {
- t.Error("expexted", ex, "got", bs)
- }
- bs = bs[:4]
- bs.Set(3)
- ex = BitString{true, false, false, true}
- if !bs.Equal(ex) {
- t.Error("expexted", ex, "got", bs)
- }
- bs.Clear(0)
- if bs.IsSet(0) {
- t.Error("got", bs)
- }
-}
diff --git a/ber/bool.go b/ber/bool.go
deleted file mode 100644
index 484ecb5..0000000
--- a/ber/bool.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package ber
-
-import "io"
-
-func UnmarshalBool(r io.ByteReader) bool {
- b, _ := r.ReadByte()
- return b != 0x00
-}
-
-func MarshalBool(w io.ByteWriter, b bool) {
- if b {
- w.WriteByte(0xFF)
- } else {
- w.WriteByte(0)
- }
-}
diff --git a/ber/bool_test.go b/ber/bool_test.go
deleted file mode 100644
index 1eae7e6..0000000
--- a/ber/bool_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type boolTest struct {
- in bool
- out byte
-}
-
-var boolTestData = []boolTest{
- {true, 0xFF},
- {false, 0x00},
-}
-
-func TestBool(t *testing.T) {
- for _, test := range boolTestData {
- buf := &bytes.Buffer{}
- MarshalBool(buf, test.in)
- a, _ := buf.ReadByte()
- if a != test.out {
- t.Error(test.in, "expected", test.out, "got", a)
- }
- buf.WriteByte(test.out)
- n := UnmarshalBool(buf)
- if n != test.in {
- t.Error(test.out, "expected", test.in, "got", n)
- }
- }
-}
diff --git a/ber/class.go b/ber/class.go
index ab455f1..32c1564 100644
--- a/ber/class.go
+++ b/ber/class.go
@@ -1,8 +1,14 @@
package ber
-import "io"
+import "fmt"
-type Class byte
+type Header struct {
+ Class
+ Kind
+ Tag
+}
+
+type Class int
const (
classUniversal Class = iota << 6
@@ -21,7 +27,7 @@ var classNames = map[Class]string{
func (c Class) String() string { return classNames[c] }
-type Kind byte
+type Kind int
const (
kindPrimitive Kind = iota << 5
@@ -107,19 +113,10 @@ var tagNames = map[Tag]string{
func (t Tag) String() string { return tagNames[t] }
-func Ident(r io.ByteReader) (Class, Kind, Tag) {
- b, _ := r.ReadByte()
- c := Class(b) & classMask
- k := Kind(b) & kindMask
- t := Tag(b) & tagMask
- if t == tagMask {
- t = Tag(Debase128(r))
+func (h Header) String() string {
+ f := "%v %v %v"
+ if h.Class != classUniversal {
+ f = "%v %v %d"
}
- return c, k, t
-}
-
-func MarshalClass(c Class, k Kind, t Tag) []byte {
- tag := base128(int(t))
- tag[0] |= byte(c) | byte(k)
- return tag
+ return fmt.Sprintf(f, h.Class, h.Kind, h.Tag)
}
diff --git a/ber/class_test.go b/ber/class_test.go
deleted file mode 100644
index 2eac220..0000000
--- a/ber/class_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ber
-
-import (
- "bytes"
- "fmt"
-)
-
-var berTestData = []byte{
- 0x02, 0x04, 0x0A, 0x30,
- 0x40, 0x61, 0x7E,
- 0x80, 0xA1, 0xBE,
-}
-
-func ExampleIdent() {
- for _, test := range berTestData {
- c, k, t := Ident(bytes.NewBuffer([]byte{test}))
- if c == classUniversal {
- fmt.Printf("%#x: %v %v %v\n",
- test, c, k, t)
- } else {
- fmt.Printf("%#x: %v %v %#x\n",
- test, c, k, byte(t))
- }
- }
- // Output:
- // 0x2: Universal Primitive Integer
- // 0x4: Universal Primitive Octet String
- // 0xa: Universal Primitive Enumerated
- // 0x30: Universal Constructed Sequence (Of)
- // 0x40: Application Primitive 0x0
- // 0x61: Application Constructed 0x1
- // 0x7e: Application Constructed 0x1e
- // 0x80: Context-specific Primitive 0x0
- // 0xa1: Context-specific Constructed 0x1
- // 0xbe: Context-specific Constructed 0x1e
-}
diff --git a/ber/new/common.go b/ber/common.go
index 7c4f496..7c4f496 100644
--- a/ber/new/common.go
+++ b/ber/common.go
diff --git a/ber/dump.go b/ber/dump.go
index da2c8bf..6faca25 100644
--- a/ber/dump.go
+++ b/ber/dump.go
@@ -1,52 +1,40 @@
package ber
import (
- "bytes"
"fmt"
)
func Dump(b []byte) string {
- return dump(bytes.NewBuffer(b), 0)
+ return newState(b).dump(0)
}
-func short(b []byte) string {
- if len(b) > 5 {
- return fmt.Sprint(b[:5], " ...")
+func (s *state) dump(indent int) string {
+ if s.Len() == 0 {
+ return ""
}
- return fmt.Sprint(b)
-}
-
-func dump(r *bytes.Buffer, indent int) (s string) {
- class, kind, tag, _, value := Split(r)
-
- s += fmt.Sprintf("%*s", indent*2, "")
-
- switch class {
- case classUniversal:
- switch tag {
- case tagInteger:
- s += fmt.Sprintln(tag, UnmarshalInt(value))
- case tagObjectIdentifier:
- s += fmt.Sprintln(tag, UnmarshalOID(value))
- case tagBitString:
- s += fmt.Sprintln(tag, UnmarshalBitString(value))
- case tagIA5String, tagOctetString:
- s += fmt.Sprintln(tag, string(value))
- case tagBoolean:
- s += fmt.Sprintln(tag, UnmarshalBool(value[0]))
- default:
- s += fmt.Sprintln(tag, kind, short(value))
+ //fmt.Printf("%*s%x %x\n", 2*indent, "", s.Len(), s.Bytes())
+ for s.Len() > 0 {
+ h := s.unmarshalClass()
+ fmt.Printf("%*s%v: ", 2*indent, "", h)
+ if h.Class == classUniversal && h.Kind == kindPrimitive {
+ switch h.Tag {
+ case tagInteger, tagEnumerated:
+ fmt.Println(s.unmarshalInt())
+ case tagBoolean:
+ fmt.Println(s.unmarshalBool())
+ case tagObjectIdentifier:
+ fmt.Println(s.unmarshalOID())
+ case tagBitString:
+ fmt.Println(s.unmarshalBitString())
+ case tagIA5String, tagOctetString:
+ fmt.Println(s.unmarshalString())
+ default:
+ fmt.Println(s.next())
+ }
+ } else {
+ fmt.Println("→")
+ s.subState().dump(indent + 1)
}
- default:
- s += fmt.Sprintln(class, kind, byte(tag), short(value))
- }
-
- if len(value) > 0 && kind != kindPrimitive {
- s += dump(bytes.NewBuffer(value), indent+1)
- }
-
- if r.Len() > 0 {
- s += dump(r, indent)
}
- return
+ return s.dump(indent)
}
diff --git a/ber/encode.go b/ber/encode.go
new file mode 100644
index 0000000..87f19f1
--- /dev/null
+++ b/ber/encode.go
@@ -0,0 +1,118 @@
+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
+ }
+ 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)
+}
+
+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
+ case reflect.Struct:
+ return structEncoder
+ case reflect.Slice:
+ return sliceEncoder
+ 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)
+}
+
+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 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 structEncoder(e *encodeState, v reflect.Value) {
+ /*
+ sube := &encodeState{}
+ for i := 0; i < v.NumField(); i++ {
+ sube.reflectValue(v.Field(i))
+ }
+ b := sube.Bytes()
+ l := MarshalLen(len(b))
+ t := MarshalClass(classUniversal, kindConstructed, tagSequence)
+ e.Write(t)
+ e.Write(l)
+ e.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())
+ }
+ */
+}
diff --git a/ber/int.go b/ber/int.go
deleted file mode 100644
index df48fa3..0000000
--- a/ber/int.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package ber
-
-func UnmarshalInt(b []byte) (i int) {
- neg := b[0]&0x80 != 0
- for _, v := range b {
- if neg {
- v = ^v
- }
- i <<= 8
- i |= int(v)
- }
- if neg {
- i = ^i
- }
- return
-}
-
-func intLen(i int) (n int) {
- for ; i > 127; i >>= 8 {
- n++
- }
- for ; i < -128; i >>= 8 {
- n++
- }
- return n + 1
-}
-
-func MarshalInt(i int) (b []byte) {
- for n := intLen(i); n > 0; n-- {
- b = append(b, byte(i>>uint((n-1)*8)))
- }
- return
-}
diff --git a/ber/int_test.go b/ber/int_test.go
deleted file mode 100644
index ba1e5b0..0000000
--- a/ber/int_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type intTest struct {
- in int
- out []byte
-}
-
-var intTestData = []intTest{
- {0, []byte{0x00}},
- {127, []byte{0x7F}},
- {128, []byte{0x00, 0x80}},
- {256, []byte{0x01, 0x00}},
- {-128, []byte{0x80}},
- {-129, []byte{0xFF, 0x7F}},
- {8388607, []byte{0x7f, 0xFF, 0xFF}},
- {-136, []byte{0xFF, 0x78}},
- {-8388607, []byte{0x80, 0x00, 0x01}},
-}
-
-func TestInt(t *testing.T) {
- for _, test := range intTestData {
- a := MarshalInt(test.in)
- if !bytes.Equal(a, test.out) {
- t.Error(test.in, "expected", test.out, "got", a)
- }
- n := UnmarshalInt(test.out)
- if n != test.in {
- t.Error(test.out, "expected", test.in, "got", n)
- }
- }
-}
diff --git a/ber/len.go b/ber/len.go
deleted file mode 100644
index 5df8288..0000000
--- a/ber/len.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package ber
-
-import (
- "io"
-)
-
-func UnmarshalLen(r io.ByteReader) int {
- b, _ := r.ReadByte()
- if b&0x80 == 0 {
- return int(b)
- }
- n := int(b & 0x7f)
- var i int
- for k := 0; k <= n; k++ {
- b, _ := r.ReadByte()
- i |= int(b) << uint(k*8)
- }
- return i
-}
-
-func unmarshalLen(b []byte) (i, n int) {
- if b[0]&0x80 == 0 {
- return int(b[0]), 1
- }
- n = int(b[0] & 0x7f)
- for k := 0; k <= n; k++ {
- i |= int(b[k]) << uint((k-1)*8)
- }
- return i, n + 1
-}
-
-func lenLen(i int) (n int) {
- for ; i > 255; i >>= 8 {
- n++
- }
- return n + 1
-}
-
-func MarshalLen(w io.ByteWriter, i int) {
- if i < 0x80 {
- w.WriteByte(byte(i))
- return
- }
- n := lenLen(i)
- w.WriteByte(byte(n) | 0x80)
- for ; n > 0; n-- {
- w.WriteByte(byte(i) >> uint(n-1) * 8)
- }
- return
-}
diff --git a/ber/len_test.go b/ber/len_test.go
deleted file mode 100644
index dc4e4ea..0000000
--- a/ber/len_test.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type lenTest struct {
- in int
- out []byte
-}
-
-var lenTestData = []lenTest{
- {0, []byte{0x00}},
- {23, []byte{0x17}},
- {193, []byte{0x81, 0xc1}},
- {240, []byte{0x81, 0xf0}},
- {257, []byte{0x82, 0x01, 0x01}},
-}
-
-func TestLen(t *testing.T) {
- for _, test := range lenTestData {
- buf := &bytes.Buffer{}
- MarshalLen(buf, test.in)
- a := buf.Bytes()
- if !bytes.Equal(a, test.out) {
- t.Error(test.in, "expected", test.out, "got", a)
- }
- n := UnmarshalLen(bytes.NewBuffer(test.out))
- if n != test.in {
- t.Error(test.out, "expected", test.in, "got", n)
- }
- }
-}
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)
}
diff --git a/ber/marshal_test.go b/ber/marshal_test.go
deleted file mode 100644
index 688c593..0000000
--- a/ber/marshal_test.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package ber
-
-import "testing"
-
-func TestMarschal(t *testing.T) {
- i := 42
- b, err := Marshal(i)
- if err != nil {
- t.Error(b, err)
- }
-}
diff --git a/ber/new/class.go b/ber/new/class.go
deleted file mode 100644
index 094c804..0000000
--- a/ber/new/class.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package ber
-
-import "fmt"
-
-type Header struct {
- Class
- Kind
- Tag
-}
-
-type Class int
-
-const (
- classUniversal Class = iota << 6
- classApplication
- classContextSpecific
- classPrivate
- classMask Class = 3 << 6
-)
-
-var classNames = map[Class]string{
- classUniversal: "Universal",
- classApplication: "Application",
- classContextSpecific: "Context-specific",
- classPrivate: "Private",
-}
-
-func (c Class) String() string { return classNames[c] }
-
-type Kind int
-
-const (
- kindPrimitive Kind = iota << 5
- kindConstructed
- kindMask Kind = 1 << 5
-)
-
-var kindNames = map[Kind]string{
- kindPrimitive: "Primitive",
- kindConstructed: "Constructed",
-}
-
-func (k Kind) String() string { return kindNames[k] }
-
-type Tag int
-
-const (
- tagEOT Tag = iota
- tagBoolean
- tagInteger
- tagBitString
- tagOctetString
- tagNull
- tagObjectIdentifier
- tagObjectDescriptor
- tagInstanceOf
- tagReal
- tagEnumerated
- tagEmbeddedPDV
- tagUTF8String
- tagRelativeOID
- _
- _
- tagSequence // SequenceOf
- tagSet // SetOf
- tagNumericString
- tagPrintableString
- tagTeletexString // T61String
- tagVideotexString
- tagIA5String
- tagUTCTime
- tagGeneralizedTime
- tagGraphicString
- tagVisibleString // ISO646String
- tagGeneralString
- tagUniversalString
- tagCharacterString
- tagBMPString
- tagMask Tag = (1 << 5) - 1
-)
-
-var tagNames = map[Tag]string{
- tagEOT: "End-of-Content",
- tagBoolean: "Boolean",
- tagInteger: "Integer",
- tagBitString: "Bit String",
- tagOctetString: "Octet String",
- tagNull: "Null",
- tagObjectIdentifier: "Object Identifier",
- tagObjectDescriptor: "Object Descriptor",
- tagInstanceOf: "Instance Of",
- tagReal: "Real",
- tagEnumerated: "Enumerated",
- tagEmbeddedPDV: "Embedded PDV",
- tagUTF8String: "UTF8 String",
- tagRelativeOID: "Relative OID",
- tagSequence: "Sequence (Of)",
- tagSet: "Set (Of)",
- tagNumericString: "Numeric String",
- tagPrintableString: "Printable String",
- tagTeletexString: "Teletext String",
- tagVideotexString: "Videotex String",
- tagIA5String: "IA5 String",
- tagUTCTime: "UTC Time",
- tagGeneralizedTime: "Generalized Time",
- tagGraphicString: "Graphic String",
- tagVisibleString: "Visible String",
- tagGeneralString: "General String",
- tagUniversalString: "Universal String",
- tagCharacterString: "Character String",
- tagBMPString: "BMP String",
-}
-
-func (t Tag) String() string { return tagNames[t] }
-
-func (s *state) ident() Header {
- b, _ := s.ReadByte()
- tag := Tag(b) & tagMask
- if tag == tagMask {
- tag = Tag(s.unmarshalBase128())
- }
- return Header{
- Class: Class(b) & classMask,
- Kind: Kind(b) & kindMask,
- Tag: tag,
- }
-}
-
-func (h Header) String() string {
- f := "%v %v %v"
- if h.Class != classUniversal {
- f = "%v %v %d"
- }
- return fmt.Sprintf(f, h.Class, h.Kind, h.Tag)
-}
diff --git a/ber/new/dump.go b/ber/new/dump.go
deleted file mode 100644
index 330bc7a..0000000
--- a/ber/new/dump.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package ber
-
-import (
- "fmt"
-)
-
-func Dump(b []byte) string {
- return newState(b).dump(0)
-}
-
-func (s *state) dump(indent int) string {
- if s.Len() == 0 {
- return ""
- }
- //fmt.Printf("%*s%x %x\n", 2*indent, "", s.Len(), s.Bytes())
- for s.Len() > 0 {
- h := s.ident()
- fmt.Printf("%*s%v: ", 2*indent, "", h)
- if h.Class == classUniversal && h.Kind == kindPrimitive {
- switch h.Tag {
- case tagInteger, tagEnumerated:
- fmt.Println(s.unmarshalInt())
- case tagBoolean:
- fmt.Println(s.unmarshalBool())
- case tagObjectIdentifier:
- fmt.Println(s.unmarshalOID())
- case tagBitString:
- fmt.Println(s.unmarshalBitString())
- case tagIA5String, tagOctetString:
- fmt.Println(s.unmarshalString())
- default:
- fmt.Println(s.next())
- }
- } else {
- fmt.Println("→")
- s.subState().dump(indent + 1)
- }
- }
- return s.dump(indent)
-}
diff --git a/ber/new/marshal.go b/ber/new/marshal.go
deleted file mode 100644
index ed63be6..0000000
--- a/ber/new/marshal.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package ber
-
-func lenLen(i int) int {
- n := 1
- for ; i > 255; i >>= 8 {
- n++
- }
- return n
-}
-
-func (s *state) marshalLen(val int) {
- if val < 0x80 {
- s.WriteByte(byte(val))
- return
- }
- n := lenLen(val)
- s.WriteByte(byte(n) | 0x80)
- for ; n > 0; n-- {
- s.WriteByte(byte(val >> uint((n-1)*8)))
- }
-}
-
-func (s *state) marshalBool(val bool) {
- s.marshalLen(1)
- if val {
- s.WriteByte(0xff)
- } else {
- s.WriteByte(0)
- }
-}
-
-func intLen(i int) int {
- n := 1
- for ; i > 127; i >>= 8 {
- n++
- }
- for ; i < -128; i >>= 8 {
- n++
- }
- return n
-}
-
-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 (s *state) marshalString(val string) {
- s.marshalLen(len(val))
- s.Write([]byte(val))
-}
-
-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 (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 (s *state) marshalBitString(val BitString) {
- pad := (8 - len(val)%8) % 8
- l := len(val) / 8
- if pad != 0 {
- l++
- }
- 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)
-}
diff --git a/ber/obj.go b/ber/obj.go
deleted file mode 100644
index 3de31b7..0000000
--- a/ber/obj.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package ber
-
-import (
- "bytes"
- "io"
- "strconv"
- "strings"
-)
-
-type OID []int
-
-func MarshalOID(obj OID) []byte {
- if len(obj) < 2 || obj[0] > 2 {
- return nil
- }
- if obj[0] < 2 && obj[1] > 39 {
- return nil
- }
- buf := &bytes.Buffer{}
- MarshalLen(buf, len(obj))
- buf.Write(base128(obj[0]*40 + obj[1]))
- for _, o := range obj[2:] {
- buf.Write(base128(o))
- }
- return buf.Bytes()
-}
-
-func (o OID) Marshal() ([]byte, error) {
- return MarshalOID(o), nil
-}
-
-func UnmarshalOID(r io.ByteReader) (o OID) {
- l := UnmarshalLen(r)
- v := Debase128(r)
- if v < 80 {
- o = OID{v / 40, v % 40}
- } else {
- o = OID{2, v - 80}
- }
-
- for i := 0; i < l; i++ {
- o = append(o, Debase128(r))
- }
- return
-}
-
-func (o OID) String() string {
- s := make([]string, len(o))
- for i, v := range o {
- s[i] = strconv.Itoa(v)
- }
- return strings.Join(s, ".")
-}
-
-func (o OID) Equal(a OID) bool {
- if len(o) != len(a) {
- return false
- }
- for i := 0; i < len(o); i++ {
- if o[i] != a[i] {
- return false
- }
- }
- return true
-}
diff --git a/ber/obj_test.go b/ber/obj_test.go
deleted file mode 100644
index 53ea7f5..0000000
--- a/ber/obj_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type oidTest struct {
- oid OID
- out []byte
- valid bool
-}
-
-var oidTestData = []oidTest{
- {OID{1, 3, 12, 0, 218},
- []byte{0x2B, 0x0C, 0x00, 0x81, 0x5A}, true},
- {OID{1, 3, 12, 0, 285, 200},
- []byte{0x2B, 0x0C, 0x00, 0x82, 0x1D, 0x81, 0x48}, true},
- {OID{}, []byte{}, false},
- {OID{0, 39}, []byte{0x27}, true},
- {OID{1, 39}, []byte{0x4f}, true},
- {OID{1, 40}, []byte{}, false},
- {OID{2, 40}, []byte{0x78}, true},
-}
-
-func TestOID(t *testing.T) {
- for _, test := range oidTestData {
- oid := MarshalOID(test.oid)
- if !bytes.Equal(oid, test.out) {
- t.Error(test.oid, "expected", test.out, "got", oid)
- }
- out := UnmarshalOID(test.out)
- if test.valid && !out.Equal(test.oid) {
- t.Error(test.out, "expected", test.oid, "got", out)
- }
- }
-}
diff --git a/ber/packet.go b/ber/packet.go
deleted file mode 100644
index ea90240..0000000
--- a/ber/packet.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package ber
-
-import "io"
-
-func Split(r io.ByteReader) (c Class, k Kind, t Tag, l int, v []byte) {
- c, k, t = Ident(r)
- l = UnmarshalLen(r)
- if l > 0 {
- v = make([]byte, l)
- for i := 0; i < l; i++ {
- v[i], _ = r.ReadByte()
- }
- }
- return
-}
diff --git a/ber/string.go b/ber/string.go
deleted file mode 100644
index 98eb617..0000000
--- a/ber/string.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package ber
-
-func MarshalString(s string) []byte {
- return []byte(s)
-}
-
-func UnmarshalString(b []byte) string {
- return string(b)
-}
diff --git a/ber/string_test.go b/ber/string_test.go
deleted file mode 100644
index 04d1fa1..0000000
--- a/ber/string_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package ber
-
-import (
- "bytes"
- "testing"
-)
-
-type stringTest struct {
- in string
- out []byte
-}
-
-var stringTestData = []stringTest{
- {"111", []byte{0x31, 0x31, 0x31}},
- {"0A16", []byte{0x30, 0x41, 0x31, 0x36}},
-}
-
-func TestString(t *testing.T) {
- for _, test := range stringTestData {
- a := MarshalString(test.in)
- if !bytes.Equal(a, test.out) {
- t.Error(test.in, "expexted", test.out, "got", a)
- }
-
- b := UnmarshalString(test.out)
- if b != test.in {
- t.Error(test.out, "expexted", test.in, "got", b)
- }
- }
-}
diff --git a/ber/new/unmarshal.go b/ber/unmarshal.go
index b29eba5..487fb02 100644
--- a/ber/new/unmarshal.go
+++ b/ber/unmarshal.go
@@ -82,3 +82,16 @@ func (s *state) unmarshalBitString() BitString {
}
return bs
}
+
+func (s *state) unmarshalClass() Header {
+ b, _ := s.ReadByte()
+ tag := Tag(b) & tagMask
+ if tag == tagMask {
+ tag = Tag(s.unmarshalBase128())
+ }
+ return Header{
+ Class: Class(b) & classMask,
+ Kind: Kind(b) & kindMask,
+ Tag: tag,
+ }
+}