aboutsummaryrefslogtreecommitdiff
path: root/ber/marshal.go
blob: 28082696e307a6f044286a612cd2fb9c64402b86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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)
}

func (s *state) marshalClass(h Header) {
	head := byte(h.Class) | byte(h.Kind)
	if h.Tag < tagMask {
		s.WriteByte(head | byte(h.Tag))
	} else {
		s.WriteByte(head | byte(tagMask))
		s.marshalBase128(int(h.Tag))
	}
}