-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtypes.go
103 lines (78 loc) · 1.89 KB
/
types.go
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
package dextk
import (
"errors"
"fmt"
"strings"
)
var (
ErrEmptyTypeDesc = errors.New("empty type desc")
ErrBadTypeDesc = errors.New("malformed type desc")
)
func (r *Reader) ReadTypeAndParse(id uint32) (TypeDescriptor, error) {
var res TypeDescriptor
typeDef, err := r.ReadType(id)
if err != nil {
return res, err
}
typeDesc, err := r.ReadString(typeDef.DescriptorStringID)
if err != nil {
return res, err
}
return ParseTypeDescriptor(typeDesc)
}
type TypeDescriptor struct {
Type uint8
ArrayLength int
ClassName String
}
func ParseTypeDescriptor(value String) (TypeDescriptor, error) {
var res TypeDescriptor
l := len(value.Raw)
if l == 0 {
return res, ErrEmptyTypeDesc
}
for value.Raw[res.ArrayLength] == '[' {
res.ArrayLength++
// Ensure there is a next character
if res.ArrayLength == l {
return res, fmt.Errorf("%w: %v", ErrBadTypeDesc, value)
}
}
res.Type = uint8(value.Raw[res.ArrayLength])
// Check if a string
if res.Type != 'L' {
// Only a single character should appear if not a string
if res.ArrayLength+1 != l {
return res, fmt.Errorf("%w: %v", ErrBadTypeDesc, value)
}
return res, nil
}
if value.Raw[l-1] != ';' {
return res, fmt.Errorf("%w: %v", ErrBadTypeDesc, value)
}
if l-2-res.ArrayLength <= 0 {
return res, fmt.Errorf("%w: %v", ErrBadTypeDesc, value)
}
res.ClassName = StringFromUTF16(value.Raw[1+res.ArrayLength : l-1])
return res, nil
}
func (d TypeDescriptor) String() string {
ap := strings.Repeat("[", d.ArrayLength)
if d.Type == 'L' {
return fmt.Sprintf("%vL%s;", ap, d.ClassName)
}
return fmt.Sprintf("%v%c", ap, d.Type)
}
func (d TypeDescriptor) Base() TypeDescriptor {
return TypeDescriptor{
Type: d.Type,
ArrayLength: 0,
ClassName: d.ClassName,
}
}
func (d TypeDescriptor) IsArray() bool {
return d.ArrayLength != 0
}
func (d TypeDescriptor) IsClass() bool {
return d.Type == 'L'
}