-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmap.go
113 lines (86 loc) · 2.09 KB
/
map.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
104
105
106
107
108
109
110
111
112
113
package ikea
import (
"encoding/binary"
"fmt"
"io"
"math"
"reflect"
"sync"
)
var mapIndex = sync.Map{}
func getMapHandlerFromType(t reflect.Type) readWriter {
infoV, found := mapIndex.Load(t.String())
if found {
return infoV.(readWriter)
}
t.Key()
info := &mapReadWriter{
mapType: t,
keyType: t.Key(),
keyHandler: getTypeHandler(t.Key()),
valueType: t.Elem(),
valueHandler: getTypeHandler(t.Elem()),
}
mapIndex.Store(t.String(), info)
return info
}
var _ variableReadWriter = (*mapReadWriter)(nil)
type mapReadWriter struct {
variable
mapType reflect.Type
keyType, valueType reflect.Type
keyHandler, valueHandler readWriter
}
func (s *mapReadWriter) readVariable(r io.Reader, v reflect.Value) error {
b := make([]byte, 4)
if _, err := io.ReadFull(r, b); err != nil {
return err
}
ul := binary.BigEndian.Uint32(b)
if ul > math.MaxInt32 {
return fmt.Errorf("transmitted map size too large (%d>%d)", ul, math.MaxInt32)
}
l := int(ul)
mp := reflect.MakeMapWithSize(s.mapType, l)
for i := 0; i < l; i++ {
key := reflect.Indirect(reflect.New(s.keyType))
val := reflect.Indirect(reflect.New(s.valueType))
if err := handleVariableReader(r, s.keyHandler, key); err != nil {
return err
}
if err := handleVariableReader(r, s.valueHandler, val); err != nil {
return err
}
mp.SetMapIndex(key, val)
}
v.Set(mp)
return nil
}
func (s *mapReadWriter) writeVariable(w io.Writer, v reflect.Value) error {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, uint32(v.Len()))
if _, err := w.Write(b); err != nil {
return err
}
it := v.MapRange()
for it.Next() {
if err := handleVariableWriter(w, s.keyHandler, it.Key()); err != nil {
return err
}
if err := handleVariableWriter(w, s.valueHandler, it.Value()); err != nil {
return err
}
}
return nil
}
func (s *mapReadWriter) vLength(v reflect.Value) int {
size := 4
for _, key := range v.MapKeys() {
val := v.MapIndex(key)
l := handleVariableLength(s.keyHandler, key)
size += l
l = handleVariableLength(s.valueHandler, val)
size += l
}
return size
}