-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutils.go
180 lines (162 loc) · 3.73 KB
/
utils.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package go_jeans
import (
"encoding/binary"
"errors"
"io"
"math"
"unsafe"
)
// PacketType 头长度 + data
type PacketType uint8
const (
// PacketType8 1字节 + data
PacketType8 PacketType = iota
PacketType16
PacketType24
PacketType32
PacketType64
)
var pLimitErr = errors.New("PackN err: 'data' exceeds the limit length")
var ptErr = errors.New("PacketType err: invalid packageType")
var (
BufferSize = 256
BaseBufferSize = 128
SliceBufferSize = 256
)
const (
_false uint8 = iota
_true
)
type slice struct {
ptr unsafe.Pointer
len int
cap int
}
// PackN 将一个字节切片重新封装成:长度 + 数据
func PackN(data []byte, pLen PacketType) ([]byte, error) {
var buf []byte
var headerLen uint64
switch pLen {
case PacketType8:
headerLen = math.MaxUint8
buf = []byte{byte(len(data))}
case PacketType16:
headerLen = math.MaxUint16
buf = make([]byte, 2)
binary.LittleEndian.PutUint16(buf, uint16(len(data)))
case PacketType24:
headerLen = 0x00FFFFFF
lb := len(data)
buf = []byte{
byte(lb),
byte(lb >> 8),
byte(lb >> 16),
}
case PacketType32:
headerLen = math.MaxUint32
buf = make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(len(data)))
case PacketType64:
headerLen = math.MaxUint64
buf = make([]byte, 8)
binary.LittleEndian.PutUint64(buf, uint64(len(data)))
default:
return nil, ptErr
}
if uint64(len(data)) > headerLen {
return nil, pLimitErr
}
return append(buf, data...), nil
}
// LittleEndianPutUint24 使用小端实现对u转换成3字节的正整数切片
func LittleEndianPutUint24(n uint32, b []byte) {
b[0] = byte(n)
b[1] = byte(n >> 8)
b[2] = byte(n >> 16)
}
// LittleEndianUint24 转换为3字节的uint32
func LittleEndianUint24(b []byte) (n uint32) {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16
}
// UnpackN 入参一个reader,返回一个有由Pack、PackN打包的完整的切片
func UnpackN(r io.Reader, pLen PacketType) (data []byte, err error) {
return UnpackBufferN(r, make([]byte, 128), pLen)
}
func UnpackBufferN(r io.Reader, buf []byte, pLen PacketType) (data []byte, err error) {
var packHeaderLen uint64
switch pLen {
case PacketType8:
_, err = io.ReadFull(r, buf[:1])
if err != nil {
return nil, err
}
packHeaderLen = uint64(buf[0])
case PacketType16:
_, err = io.ReadFull(r, buf[:2])
if err != nil {
return nil, err
}
packHeaderLen = uint64(binary.LittleEndian.Uint16(buf[:2]))
case PacketType24:
_, err = io.ReadFull(r, buf[:3])
if err != nil {
return nil, err
}
packHeaderLen = uint64(uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16)
case PacketType32:
_, err = io.ReadFull(r, buf[:4])
if err != nil {
return nil, err
}
packHeaderLen = uint64(binary.LittleEndian.Uint32(buf[:4]))
case PacketType64:
_, err := io.ReadFull(r, buf[:8])
if err != nil {
return nil, err
}
packHeaderLen = binary.LittleEndian.Uint64(buf[:8])
default:
return nil, pLimitErr
}
if v := uint64(len(buf)); v < packHeaderLen {
buf = append(buf, make([]byte, packHeaderLen-v)...)
}
_, err = io.ReadFull(r, buf[:packHeaderLen])
return buf[:packHeaderLen], err
}
type str struct {
s string
cap int
}
func stringToBytes(s *string) *[]byte {
return (*[]byte)(unsafe.Pointer(&str{*s, len(*s)}))
}
func bytesToString(buf []byte) *string {
return (*string)(unsafe.Pointer(&buf))
}
func littleAppendUint64(b []byte, v uint64) []byte {
return append(b,
byte(v),
byte(v>>8),
byte(v>>16),
byte(v>>24),
byte(v>>32),
byte(v>>40),
byte(v>>48),
byte(v>>56),
)
}
func littleAppendUint32(b []byte, v uint32) []byte {
return append(b,
byte(v),
byte(v>>8),
byte(v>>16),
byte(v>>24),
)
}
func littleAppendUint16(b []byte, v uint16) []byte {
return append(b,
byte(v),
byte(v>>8),
)
}