-
Notifications
You must be signed in to change notification settings - Fork 2
/
slice.go
67 lines (57 loc) · 1.59 KB
/
slice.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
package unsafekit
import (
"fmt"
"reflect"
"runtime"
"unsafe"
"github.com/insolar/vanilla/longbits"
)
// WARNING! The given struct MUST be immutable. Expects struct ptr.
// WARNING! This method violates unsafe pointer-conversion rules.
// You MUST make sure that (v) stays alive while the resulting ByteString is in use.
func WrapSlice(v interface{}) longbits.ByteString {
vt := reflect.ValueOf(v)
if vt.Kind() != reflect.Slice {
panic("illegal value")
}
return wrapSlice(vt)
}
func wrapSlice(vt reflect.Value) longbits.ByteString {
n := uintptr(vt.Len()) * vt.Type().Elem().Size()
if n == 0 {
return ""
}
return wrapUnsafePtr(vt.Pointer(), n)
}
func WrapSliceOf(v interface{}, mt MMapSliceType) longbits.ByteString {
vt := reflect.ValueOf(v)
if vt.Type() != mt.ReflectType() {
panic("illegal value type")
}
return wrapSlice(vt)
}
func UnwrapAsSliceOf(s longbits.ByteString, mt MMapSliceType) interface{} {
t := mt.ReflectType()
if t.Kind() != reflect.Slice { // double-check
panic("illegal value")
}
itemSize := int(t.Elem().Size())
switch {
case len(s) == 0:
return reflect.Zero(t).Interface()
case len(s)%itemSize != 0:
panic(fmt.Sprintf("illegal value - length is unaligned: dataLen=%d itemSize=%d", len(s), itemSize))
}
slice := reflect.New(t)
itemCount := len(s) / itemSize
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(slice.Pointer()))
sliceHeader.Data = _unwrapUnsafeUintptr(s)
sliceHeader.Cap = itemCount
sliceHeader.Len = itemCount
slice = slice.Elem()
if slice.Len() != itemCount {
panic("unexpected")
}
runtime.KeepAlive(s)
return slice.Interface()
}