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  }