github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/unsafekit/mmap_type.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package unsafekit 7 8 import ( 9 "reflect" 10 11 "github.com/insolar/vanilla/longbits" 12 ) 13 14 type MemoryMapModel uint8 15 16 const ( 17 MemoryMapIncompatible MemoryMapModel = iota 18 MemoryModelDepended 19 MemoryModelIndependent 20 ) 21 22 type Unwrapper interface { 23 Unwrap(longbits.ByteString) interface{} 24 MemoryModelIndependent() bool 25 } 26 27 type MMType interface { 28 ReflectType() reflect.Type 29 MemoryModelIndependent() bool 30 } 31 32 type MMapType struct { 33 t reflect.Type 34 modelIndependent bool 35 } 36 37 func NewMMapType(t reflect.Type) (MMapType, bool) { 38 mm := MemoryModelDependencyOf(t) 39 if mm == MemoryMapIncompatible { 40 return MMapType{}, false 41 } 42 43 return MMapType{t: t, modelIndependent: mm == MemoryModelIndependent}, true 44 } 45 46 func MustMMapType(t reflect.Type, mustBeIndependent bool) MMapType { 47 switch mt, ok := NewMMapType(t); { 48 case !ok: 49 panic("illegal value - type must be memory-mappable") 50 case !mustBeIndependent || mt.MemoryModelIndependent(): 51 return mt 52 default: 53 panic("illegal value - type must be memory-mappable and memory-model independent") 54 } 55 } 56 57 type MMapSliceType struct { 58 t reflect.Type 59 modelIndependent bool 60 } 61 62 func NewMMapSliceType(t reflect.Type) (MMapSliceType, bool) { 63 if t.Kind() != reflect.Slice { 64 panic("illegal value") 65 } 66 mm := MemoryModelDependencyOf(t.Elem()) 67 if mm == MemoryMapIncompatible { 68 return MMapSliceType{}, false 69 } 70 71 return MMapSliceType{t: t, modelIndependent: mm == MemoryModelIndependent}, true 72 } 73 74 func MustMMapSliceType(t reflect.Type, mustBeIndependent bool) MMapSliceType { 75 switch mt, ok := NewMMapSliceType(t); { 76 case !ok: 77 panic("illegal value - type must be memory-mappable") 78 case !mustBeIndependent || mt.MemoryModelIndependent(): 79 return mt 80 default: 81 panic("illegal value - type must be memory-mappable and memory-model independent") 82 } 83 } 84 85 func MemoryModelDependencyOf(t reflect.Type) MemoryMapModel { 86 switch k := t.Kind(); k { 87 case reflect.Bool, reflect.Int8, reflect.Uint8: 88 return MemoryModelIndependent 89 90 case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, 91 reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, 92 reflect.Float32, reflect.Float64: 93 return MemoryModelDepended 94 95 case reflect.Complex64, reflect.Complex128: 96 // there is no information of memory representation of complex types 97 return MemoryMapIncompatible 98 99 case reflect.Array: 100 return MemoryModelDependencyOf(t.Elem()) 101 102 case reflect.Uintptr: // same as Pointer 103 return MemoryMapIncompatible 104 case reflect.Struct: 105 // 106 default: 107 return MemoryMapIncompatible 108 } 109 110 memoryModelDepended := false 111 fieldCount := t.NumField() 112 endOfPrev := uintptr(0) 113 114 for i := 0; i < fieldCount; i++ { 115 f := t.Field(i) 116 if f.Offset != endOfPrev { 117 memoryModelDepended = true 118 } 119 120 switch mt := MemoryModelDependencyOf(f.Type); mt { 121 case MemoryModelIndependent: 122 // 123 case MemoryModelDepended: 124 memoryModelDepended = true 125 case MemoryMapIncompatible: 126 return MemoryMapIncompatible 127 default: 128 panic("unexpected") 129 } 130 131 endOfPrev += f.Type.Size() 132 } 133 if memoryModelDepended || endOfPrev != t.Size() { 134 return MemoryModelDepended 135 } 136 return MemoryModelIndependent 137 } 138 139 func (v MMapType) IsZero() bool { 140 return v.t == nil 141 } 142 143 func (v MMapType) ReflectType() reflect.Type { 144 if v.t == nil { 145 panic("illegal state") 146 } 147 return v.t 148 } 149 150 func (v MMapType) MemoryModelIndependent() bool { 151 return v.modelIndependent 152 } 153 154 func (v MMapType) Size() int { 155 return int(v.t.Size()) 156 } 157 158 func (v MMapType) SliceOf() MMapSliceType { 159 return MMapSliceType{reflect.SliceOf(v.t), v.modelIndependent} 160 } 161 162 func (v MMapType) Unwrap(s longbits.ByteString) interface{} { 163 return UnwrapAs(s, v) 164 } 165 166 func (v MMapSliceType) IsZero() bool { 167 return v.t == nil 168 } 169 170 func (v MMapSliceType) ReflectType() reflect.Type { 171 if v.t == nil { 172 panic("illegal state") 173 } 174 return v.t 175 } 176 177 func (v MMapSliceType) MemoryModelIndependent() bool { 178 return v.modelIndependent 179 } 180 181 func (v MMapSliceType) Elem() MMapType { 182 return MMapType{v.t.Elem(), v.modelIndependent} 183 } 184 185 func (v MMapSliceType) ElemReflectType() reflect.Type { 186 return v.t.Elem() 187 } 188 189 func (v MMapSliceType) Unwrap(s longbits.ByteString) interface{} { 190 return UnwrapAsSliceOf(s, v) 191 }