func arrayEncoder(typ reflect.Type) (typeEncoder, error) { al := typ.Len() etyp := typ.Elem() switch etyp.Kind() { case reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: // Take advantage of the fast path in Write return func(enc *encoder, p unsafe.Pointer) error { v := reflect.NewAt(typ, p).Elem().Slice(0, al) return Write(enc, enc.order, v.Interface()) }, nil } eenc, err := makeEncoder(etyp) if err != nil { return nil, err } s := etyp.Size() return func(enc *encoder, p unsafe.Pointer) error { for ii := 0; ii < al; ii++ { if err := eenc(enc, p); err != nil { return err } p = unsafe.Pointer(uintptr(p) + s) } return nil }, nil }
func decodeArray(t reflect.Type) interface{} { slType := reflect.SliceOf(t.Elem()) slDec := getTypeDecoder(slType) _, ok := slDec.(decodeFunc) l := t.Len() return decodeReflectFunc(func(dec *Decoder, v reflect.Value) error { p := v.UnsafeAddr() var err error if ok { slice := reflect.SliceHeader{ Len: l, Cap: l, Data: p, } err = (slDec.(decodeFunc))(dec, unsafe.Pointer(&slice)) if slice.Len != l { return ErrorIncorrectLength{l, slice.Len} } } else { slice := v.Slice(0, v.Len()) ptr := reflect.New(slType) ptr.Elem().Set(slice) err = (slDec.(decodeReflectFunc))(dec, ptr.Elem()) if slice.Len() != l { return ErrorIncorrectLength{l, slice.Len()} } } return err }) }
// formFromGoType returns a suitable FITS TFORM string from a reflect.Type func formFromGoType(rt reflect.Type, htype HDUType) string { hdr := "" var t reflect.Type switch rt.Kind() { case reflect.Array: hdr = fmt.Sprintf("%d", rt.Len()) t = rt.Elem() case reflect.Slice: hdr = "Q" t = rt.Elem() default: t = rt } dict, ok := g_gotype2FITS[t.Kind()] if !ok { return "" } form, ok := dict[htype] if !ok { return "" } return hdr + form }
func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: n, err := sizeof(t.Elem()) if err != nil { return 0, err } return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s, err := sizeof(t.Field(i).Type) if err != nil { return 0, err } sum += s } return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return int(t.Size()), nil } return 0, errors.New("invalid type " + t.String()) }
func sliceDecoder(typ reflect.Type) (typeDecoder, error) { switch typ.Elem().Kind() { case reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: // Take advantage of the fast path in Read if typ.Kind() == reflect.Slice { return func(dec *decoder, v reflect.Value) error { return Read(dec, dec.order, v.Interface()) }, nil } // Array al := typ.Len() return func(dec *decoder, v reflect.Value) error { // Value must be addressable when we reach this point return Read(dec, dec.order, v.Slice(0, al).Interface()) }, nil } edec, err := makeDecoder(typ.Elem()) if err != nil { return nil, err } return func(dec *decoder, v reflect.Value) error { sl := v.Len() for ii := 0; ii < sl; ii++ { if err := edec(dec, v.Index(ii)); err != nil { return err } } return nil }, nil }
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: if s := sizeof(t.Elem()); s >= 0 { return s * t.Len() } case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr: return int(t.Size()) } return -1 }
func evalCompositeLitArrayOrSlice(ctx *Ctx, t reflect.Type, lit *CompositeLit, env *Env) (*reflect.Value, bool, error) { v := reflect.New(t).Elem() var curKey uint64 = 0 var size uint64 = 0 if t.Kind() == reflect.Array { size = uint64(t.Len()) } else { // Check all keys are valid and calculate slice size. // Elements with key are placed at the keyed position. // Elements without are placed one after the previous. // For example, []int{1, 2:1, 1} -> [1, 0, 1, 1] for _, elt := range lit.Elts { if kv, ok := elt.(*KeyValueExpr); !ok { size += 1 } else if k, ok := kv.Key.(*BasicLit); !ok || k.Kind != token.INT { return nil, false, ErrArrayKey // The limit of 2^31 elements is infered from the go implementation // The actual limit is "largest value representable by an int" } else if i, err := strconv.ParseUint(k.Value, 0, 31); err != nil { return nil, false, ErrArrayKey } else if !(i < size) { size = i + 1 } } // Allocate the slice v.Set(reflect.MakeSlice(t, int(size), int(size))) } // Fill the array or slice, the reflect interface is identical for both for _, elt := range lit.Elts { var expr ast.Expr if kv, ok := elt.(*KeyValueExpr); !ok { expr = elt } else { // We know this expression to be valid from above. curKey, _ = strconv.ParseUint(kv.Key.(*BasicLit).Value, 0, 31) expr = kv.Value } if !(curKey < size) { return nil, false, ErrArrayIndexOutOfBounds{t, curKey} } // Evaluate and set the element elem := v.Index(int(curKey)) if values, typed, err := EvalExpr(ctx, expr.(Expr), env); err != nil { return nil, false, err } else if value, err := expectSingleValue(ctx, *values, elt); err != nil { return nil, false, err } else if err := setTypedValue(elem, value, typed); err != nil { return nil, false, err } curKey += 1 } return &v, true, nil }
// Return the string that should be used to refer to the supplied type within // the given package. The output is not guaranteed to be pretty, and should be // run through a tool like gofmt afterward. // // For example, a pointer to an io.Reader may be rendered as "*Reader" or // "*io.Reader" depending on whether the package path is "io" or not. func typeString( t reflect.Type, pkgPath string) (s string) { // Is this type named? If so we use its name, possibly with a package prefix. // // Examples: // // int // string // error // gcs.Bucket // if t.Name() != "" { if t.PkgPath() == pkgPath { s = t.Name() } else { s = t.String() } return } // This type is unnamed. Recurse. switch t.Kind() { case reflect.Array: s = fmt.Sprintf("[%d]%s", t.Len(), typeString(t.Elem(), pkgPath)) case reflect.Chan: s = fmt.Sprintf("%s %s", t.ChanDir(), typeString(t.Elem(), pkgPath)) case reflect.Func: s = typeString_Func(t, pkgPath) case reflect.Interface: s = typeString_Interface(t, pkgPath) case reflect.Map: s = fmt.Sprintf( "map[%s]%s", typeString(t.Key(), pkgPath), typeString(t.Elem(), pkgPath)) case reflect.Ptr: s = fmt.Sprintf("*%s", typeString(t.Elem(), pkgPath)) case reflect.Slice: s = fmt.Sprintf("[]%s", typeString(t.Elem(), pkgPath)) case reflect.Struct: s = typeString_Struct(t, pkgPath) default: log.Panicf("Unhandled kind %v for type: %v", t.Kind(), t) } return }
func (s *Shader) assignPrimitive(ptr unsafe.Pointer, typ reflect.Type, u gl.UniformLocation) bool { switch typ.Kind() { // basic primitives case reflect.Int: u.Uniform1i(*(*int)(ptr)) case reflect.Int32: u.Uniform1i(int(*(*int32)(ptr))) case reflect.Float32: u.Uniform1f(*(*float32)(ptr)) // arrays represent vectors or matrices case reflect.Array: size := typ.Len() elemtyp := typ.Elem() switch elemtyp.Kind() { case reflect.Int32: switch size { case 2: slice := (*(*[2]int32)(ptr))[:] u.Uniform2iv(1, slice) case 3: slice := (*(*[3]int32)(ptr))[:] u.Uniform3iv(1, slice) case 4: slice := (*(*[4]int32)(ptr))[:] u.Uniform4iv(1, slice) default: return false } case reflect.Float32: switch size { case 2: slice := (*(*[2]float32)(ptr))[:] u.Uniform2fv(1, slice) case 3: slice := (*(*[3]float32)(ptr))[:] u.Uniform3fv(1, slice) case 4: slice := (*(*[4]float32)(ptr))[:] u.Uniform4fv(1, slice) case 9: matptr := (*[9]float32)(ptr) u.UniformMatrix3f(false, matptr) case 16: matptr := (*[16]float32)(ptr) u.UniformMatrix4f(false, matptr) default: return false } default: return false } default: return false } return true }
func getArrayDims(dt reflect.Type) []int { result := []int{} if dt.Kind() == reflect.Array { result = append(result, dt.Len()) for _, dim := range getArrayDims(dt.Elem()) { result = append(result, dim) } } return result }
func reifyArray( opts fieldOptions, to reflect.Value, tTo reflect.Type, val value, ) (reflect.Value, Error) { arr := castArr(val) if len(arr) != tTo.Len() { ctx := val.Context() return reflect.Value{}, raiseArraySize(ctx, val.meta(), len(arr), tTo.Len()) } return reifyDoArray(opts, to, tTo.Elem(), val, arr) }
//获取t对应的类型信息,不支持slice, function, map, pointer, interface, channel //如果parentIdx的长度>0,则表示t是strut中的字段的类型信息, t为字段对应的类型 func getKeyInfoByParent(t reflect.Type, parent *keyInfo, parentIdx []int) (ki *keyInfo, err error) { ki = &keyInfo{} //判断是否实现了hasher接口 if t.Implements(hasherT) { ki.isHasher = true return } ki.kind = t.Kind() if _, ok := engM[ki.kind]; ok { //简单类型,不需要再分解元素类型的信息 ki.index = parentIdx } else { //some types can be used as key, we can use equals to test switch ki.kind { case reflect.Chan, reflect.Slice, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface: err = NonSupportKey case reflect.Struct: if parent == nil { //parent==nil表示t不是一个嵌套的struct,所以这里需要初始化fields parent = ki ki.fields = make([]*keyInfo, 0, t.NumField()) } for i := 0; i < t.NumField(); i++ { f := t.Field(i) //skip unexported field, if len(f.PkgPath) > 0 { continue } idx := make([]int, len(parentIdx), len(parentIdx)+1) copy(idx, parentIdx) idx = append(idx, i) if fi, e := getKeyInfoByParent(f.Type, parent, idx); e != nil { err = e return } else { //fi.index = i parent.fields = append(ki.fields, fi) } } case reflect.Array: if ki.elementInfo, err = getKeyInfo(t.Elem()); err != nil { return } ki.size = t.Len() ki.index = parentIdx } } return }
func ValType(t reflect.Type) (decl string) { switch k := t.Kind(); k { case reflect.Struct: decl = "struct {\n" for i, ed := 0, t.NumField(); i < ed; i++ { ft := t.Field(i) if ft.Tag != "-" || ft.Tag.Get("goval") == "-" { s := ft.Name + " " + ValType(ft.Type) if ft.Tag != "" { s += " `" + strings.Replace("`", "\\`", string(ft.Tag), -1) + "`" } decl += indent(s) + "\n" } } decl += "}" case reflect.Array: decl = "[" + strconv.Itoa(t.Len()) + "]" + Val(t.Elem()) case reflect.Slice: decl = "[]" + Val(t.Elem()) case reflect.Chan: switch t.ChanDir() { case reflect.RecvDir: decl = "<-chan " case reflect.SendDir: decl = "chan<- " case reflect.BothDir: decl = "chan " default: panic("Didn't expect a dir other than send, recieve or both.") } decl += Val(t.Elem()) case reflect.Map: decl = "map[" + ValType(t.Key()) + "]" + ValType(t.Elem()) case reflect.Ptr: decl = "*" + ValType(t.Elem()) case reflect.Interface: decl = "interface {\n" for i, ed := 0, t.NumMethod(); i < ed; i++ { ft := t.Method(i) s := ft.Name + FormatFuncArguments(ft.Type) decl += indent(s) + "\n" } decl += "}" case reflect.Func: decl = "func" + FormatFuncArguments(t) default: return k.String() } return }
func sizeof(t reflect.Type) int { switch t := t.(type) { case *reflect.ArrayType: n := sizeof(t.Elem()) if n < 0 { return -1 } return t.Len() * n case *reflect.StructType: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case *reflect.Uint8Type: return 1 case *reflect.Uint16Type: return 2 case *reflect.Uint32Type: return 4 case *reflect.Uint64Type: return 8 case *reflect.Int8Type: return 1 case *reflect.Int16Type: return 2 case *reflect.Int32Type: return 4 case *reflect.Int64Type: return 8 case *reflect.Float32Type: return 4 case *reflect.Float64Type: return 8 } return -1 }
func encodeArray(t reflect.Type) interface{} { //Cheat by turning the array into a slice slEnc := getTypeEncoder(reflect.SliceOf(t.Elem())) l := t.Len() _, ok := slEnc.(encodeFunc) return encodeReflectFunc(func(enc *Encoder, v reflect.Value) error { if ok { slice := reflect.SliceHeader{ //Convert to slice Data: v.UnsafeAddr(), Len: l, Cap: l, } encF := slEnc.(encodeFunc) return encF(enc, unsafe.Pointer(&slice)) } else { encF := slEnc.(encodeReflectFunc) return encF(enc, v.Slice(0, v.Len())) } }) }
func evalIntIndex(ctx *Ctx, intExpr ast.Expr, env *Env, containerType reflect.Type) (int, error) { if is, typed, err := EvalExpr(ctx, intExpr.(Expr), env); err != nil { return -1, err } else if is == nil { // XXX temporary error until typed evaluation of nil return -1, errors.New("Cannot index nil type") } else if i, err := expectSingleValue(ctx, *is, intExpr); err != nil { return -1, err // XXX This untyped constant conversion is not correct, the index must evaluate exactly // to an integer. // a[2*0.5] is legal, a[2*0.4] is not. // // There is also the constraint that constant expressions such as "abc"[10] must be // in range. Fix both when constant expressions are correctly handled } else if !typed && i.Type().ConvertibleTo(reflect.TypeOf(int(0))) { result := int(i.Convert(reflect.TypeOf(int(0))).Int()) if 0 <= result && (containerType.Kind() != reflect.Array || result < containerType.Len()) { return result, nil } return -1, ErrInvalidIndex{at(ctx, intExpr), reflect.ValueOf(result), containerType} } else { var result int switch i.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: result = int(i.Int()) if result >= 0 { return result, nil } return -1, ErrInvalidIndex{at(ctx, intExpr), reflect.ValueOf(result), containerType} case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: result = int(i.Uint()) if result >= 0 { return result, nil } return -1, ErrInvalidIndex{at(ctx, intExpr), reflect.ValueOf(result), containerType} default: return -1, ErrInvalidIndex{at(ctx, intExpr), i, containerType} } } }
func NewMesh(attrs interface{}, indicies []uint32) *Mesh { mesh := new(Mesh) mesh.Attrs = attrs mesh.Indicies = indicies gl33.GenVertexArrays(1, &mesh.vao) gl33.BindVertexArray(mesh.vao) attrsValue := reflect.ValueOf(attrs) mesh.vertexBO = NewBuffer(gl33.ARRAY_BUFFER, gl33.STATIC_DRAW, attrs) vertexSpec := attrsValue.Type().Elem() if vertexSpec.Kind() != reflect.Struct && vertexSpec.Kind() != reflect.Array { panic("attrs is not a slice of structs or arrays") } var num int if vertexSpec.Kind() == reflect.Struct { num = vertexSpec.NumField() } else { num = vertexSpec.Len() } for i, offset := 0, uintptr(0); i < num; i++ { var field reflect.Type var type_ gl33.Enum var dimensions int if vertexSpec.Kind() == reflect.Struct { field = vertexSpec.Field(i).Type } else { field = vertexSpec.Elem() } if field.Kind() == reflect.Array { type_ = glType(field.Elem().Kind()) dimensions = field.Len() } else { type_ = glType(field.Kind()) dimensions = 1 } setupAttrib(gl33.Uint(i), type_, dimensions, offset, int(vertexSpec.Size())) offset += field.Size() } mesh.indexBO = NewBuffer(gl33.ELEMENT_ARRAY_BUFFER, gl33.STATIC_DRAW, indicies) return mesh }
// GetName of a type. func (opts *GenOpts) GetName(t reflect.Type) string { name := t.Name() if name != "" { pkg, _ := packageAndName(t) // Handle the case the type is in the package we are generating code for. if pkg == "" || pkg == opts.PkgName { return name } return fmt.Sprintf("%s.%s", pkg, name) } switch t.Kind() { case reflect.Ptr: return fmt.Sprintf("*%s", opts.GetName(t.Elem())) case reflect.Map: return fmt.Sprintf("map[%s]%s", opts.GetName(t.Key()), opts.GetName(t.Elem())) case reflect.Slice: return fmt.Sprintf("[]%s", opts.GetName(t.Elem())) case reflect.Chan: return fmt.Sprintf("%s %s", t.ChanDir().String(), opts.GetName(t.Elem())) case reflect.Array: return fmt.Sprintf("[%d]%s", t.Len(), opts.GetName(t.Elem())) case reflect.Func: inputs := make([]string, t.NumIn()) for i := range inputs { inputs[i] = opts.GetName(t.In(i)) } outputs := make([]string, t.NumOut()) for i := range outputs { outputs[i] = opts.GetName(t.Out(i)) } out := strings.Join(outputs, ", ") if len(outputs) > 1 { out = fmt.Sprintf("(%s)", out) } return fmt.Sprintf("func (%s) %s", strings.Join(inputs, ", "), out) default: return t.String() } }
// getType return the textual type name of given type that can be used in generated code. func (g *Generator) getType(t reflect.Type) string { if t.Name() == "" { switch t.Kind() { case reflect.Ptr: return "*" + g.getType(t.Elem()) case reflect.Slice: return "[]" + g.getType(t.Elem()) case reflect.Array: return "[" + strconv.Itoa(t.Len()) + "]" + g.getType(t.Elem()) case reflect.Map: return "map[" + g.getType(t.Key()) + "]" + g.getType(t.Elem()) } } if t.Name() == "" || t.PkgPath() == "" { return t.String() } else if t.PkgPath() == g.pkgPath { return t.Name() } // TODO: unnamed structs. return g.pkgAlias(t.PkgPath()) + "." + t.Name() }
func sliceEncoder(typ reflect.Type) (typeEncoder, error) { switch typ.Elem().Kind() { case reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: // Take advantage of the fast path in Write if typ.Kind() == reflect.Slice { return func(enc *encoder, v reflect.Value) error { return Write(enc, enc.order, v.Interface()) }, nil } // Array al := typ.Len() eenc, _ := makeEncoder(typ.Elem()) return func(enc *encoder, v reflect.Value) error { if v.CanAddr() { return Write(enc, enc.order, v.Slice(0, al).Interface()) } for ii := 0; ii < al; ii++ { if err := eenc(enc, v.Index(ii)); err != nil { return err } } return nil }, nil } eenc, err := makeEncoder(typ.Elem()) if err != nil { return nil, err } return func(enc *encoder, v reflect.Value) error { sl := v.Len() for ii := 0; ii < sl; ii++ { if err := eenc(enc, v.Index(ii)); err != nil { return err } } return nil }, nil }
func checkCompositeLitArrayOrSlice(lit *CompositeLit, t reflect.Type, env Env) (*CompositeLit, []error) { var errs, moreErrs []error eltT := t.Elem() maxIndex, curIndex := -1, 0 outOfBounds := false length := -1 if t.Kind() == reflect.Array { length = t.Len() } used := make(map[int]bool, len(lit.Elts)) // Check all keys are valid and calculate array or slice length. // Elements with key are placed at the keyed position. // Elements without are placed in the next position. // For example, []int{1, 2:1, 1} -> [1, 0, 1, 1] for i := range lit.Elts { var value ast.Expr var key Expr var avalue *Expr skipIndexChecks := false kv, ok := lit.CompositeLit.Elts[i].(*ast.KeyValueExpr) if !ok { avalue, value = &lit.Elts[i], lit.CompositeLit.Elts[i] } else { akv := &KeyValueExpr{KeyValueExpr: kv} lit.Elts[i] = akv avalue, value = &akv.Value, kv.Value // Check the array key var index int key, index, ok, moreErrs = checkArrayIndex(kv.Key, env) if !ok || moreErrs != nil { // NOTE[crc] Haven't checked the gc implementation, but // from experimentation it seems that only undefined // idents are reported. This filter should perhaps be part // of checkArrayIndex for _, err := range moreErrs { if _, ok := err.(ErrUndefined); ok { errs = append(errs, err) } } errs = append(errs, ErrBadArrayKey{key}) // Don't include this element in index calculations curIndex -= 1 skipIndexChecks = true } else { lit.indices = append(lit.indices, struct{ pos, index int }{i, index}) curIndex = index } } // finally check the value v, moreErrs := checkArrayValue(value, eltT, env) *avalue = v // These errors slide in before the check errors, but we need v if !skipIndexChecks { if maxIndex < curIndex { maxIndex = curIndex } if !outOfBounds && length != -1 && curIndex >= length { outOfBounds = true errs = append(errs, ErrArrayKeyOutOfBounds{v, t, curIndex}) } // has this index been used already if used[curIndex] { errs = append(errs, ErrDuplicateArrayKey{key, curIndex}) } used[curIndex] = true } // Add the check errors if moreErrs != nil { errs = append(errs, moreErrs...) } curIndex += 1 } lit.indices = append(lit.indices, struct{ pos, index int }{-1, -1}) if length == -1 { lit.length = maxIndex + 1 } else { lit.length = length } return lit, errs }
func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) { log.Info(Fmt("writeReflectJSON(%v, %v, %v, %v, %v)", rv, rt, w, n, err)) // Get typeInfo typeInfo := GetTypeInfo(rt) if rt.Kind() == reflect.Interface { if rv.IsNil() { // XXX ensure that typeByte 0 is reserved. WriteTo([]byte("null"), w, n, err) return } crv := rv.Elem() // concrete reflection value crt := crv.Type() // concrete reflection type if typeInfo.IsRegisteredInterface { // See if the crt is registered. // If so, we're more restrictive. _, ok := typeInfo.TypeToByte[crt] if !ok { switch crt.Kind() { case reflect.Ptr: *err = errors.New(Fmt("Unexpected pointer type %v for registered interface %v. "+ "Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name())) case reflect.Struct: *err = errors.New(Fmt("Unexpected struct type %v for registered interface %v. "+ "Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name())) default: *err = errors.New(Fmt("Unexpected type %v for registered interface %v. "+ "If this is intentional, please register it.", crt, rt.Name())) } return } } else { // We support writing unsafely for convenience. } // We don't have to write the typeByte here, // the writeReflectJSON() call below will write it. writeReflectJSON(crv, crt, w, n, err) return } if rt.Kind() == reflect.Ptr { // Dereference pointer rv, rt = rv.Elem(), rt.Elem() typeInfo = GetTypeInfo(rt) if !rv.IsValid() { // For better compatibility with other languages, // as far as tendermint/wire is concerned, // pointers to nil values are the same as nil. WriteTo([]byte("null"), w, n, err) return } // continue... } // Write Byte if typeInfo.Byte != 0x00 { WriteTo([]byte(Fmt("[%v,", typeInfo.Byte)), w, n, err) defer WriteTo([]byte("]"), w, n, err) } // All other types switch rt.Kind() { case reflect.Array: elemRt := rt.Elem() length := rt.Len() if elemRt.Kind() == reflect.Uint8 { // Special case: Bytearray bytearray := reflect.ValueOf(make([]byte, length)) reflect.Copy(bytearray, rv) WriteTo([]byte(Fmt("\"%X\"", bytearray.Interface())), w, n, err) } else { WriteTo([]byte("["), w, n, err) // Write elems for i := 0; i < length; i++ { elemRv := rv.Index(i) writeReflectJSON(elemRv, elemRt, w, n, err) if i < length-1 { WriteTo([]byte(","), w, n, err) } } WriteTo([]byte("]"), w, n, err) } case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { // Special case: Byteslices byteslice := rv.Bytes() WriteTo([]byte(Fmt("\"%X\"", byteslice)), w, n, err) } else { WriteTo([]byte("["), w, n, err) // Write elems length := rv.Len() for i := 0; i < length; i++ { elemRv := rv.Index(i) writeReflectJSON(elemRv, elemRt, w, n, err) if i < length-1 { WriteTo([]byte(","), w, n, err) } } WriteTo([]byte("]"), w, n, err) } case reflect.Struct: if rt == timeType { // Special case: time.Time t := rv.Interface().(time.Time).UTC() str := t.Format(iso8601) jsonBytes, err_ := json.Marshal(str) if err_ != nil { *err = err_ return } WriteTo(jsonBytes, w, n, err) } else { WriteTo([]byte("{"), w, n, err) wroteField := false for _, fieldInfo := range typeInfo.Fields { i, fieldType, opts := fieldInfo.unpack() fieldRv := rv.Field(i) if wroteField { WriteTo([]byte(","), w, n, err) } else { wroteField = true } WriteTo([]byte(Fmt("\"%v\":", opts.JSONName)), w, n, err) writeReflectJSON(fieldRv, fieldType, w, n, err) } WriteTo([]byte("}"), w, n, err) } case reflect.String: fallthrough case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: fallthrough case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: fallthrough case reflect.Bool: jsonBytes, err_ := json.Marshal(rv.Interface()) if err_ != nil { *err = err_ return } WriteTo(jsonBytes, w, n, err) default: PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } }
// Contract: Caller must ensure that rt is supported // (e.g. is recursively composed of supported native types, and structs and slices.) // rv and rt refer to the object we're unmarhsaling into, whereas o is the result of naiive json unmarshal (map[string]interface{}) func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) { // Get typeInfo typeInfo := GetTypeInfo(rt) if rt.Kind() == reflect.Interface { if !typeInfo.IsRegisteredInterface { // There's no way we can read such a thing. *err = errors.New(Fmt("Cannot read unregistered interface type %v", rt)) return } if o == nil { return // nil } typeByte, _, err_ := readByteJSON(o) if err_ != nil { *err = err_ return } crt, ok := typeInfo.ByteToType[typeByte] if !ok { *err = errors.New(Fmt("Byte %X not registered for interface %v", typeByte, rt)) return } crv := reflect.New(crt).Elem() readReflectJSON(crv, crt, o, err) rv.Set(crv) // NOTE: orig rv is ignored. return } if rt.Kind() == reflect.Ptr { if o == nil { return // nil } // Create new struct if rv is nil. if rv.IsNil() { newRv := reflect.New(rt.Elem()) rv.Set(newRv) rv = newRv } // Dereference pointer rv, rt = rv.Elem(), rt.Elem() typeInfo = GetTypeInfo(rt) // continue... } // Read Byte prefix if typeInfo.Byte != 0x00 { typeByte, rest, err_ := readByteJSON(o) if err_ != nil { *err = err_ return } if typeByte != typeInfo.Byte { *err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, byte(typeByte))) return } o = rest } switch rt.Kind() { case reflect.Array: elemRt := rt.Elem() length := rt.Len() if elemRt.Kind() == reflect.Uint8 { // Special case: Bytearrays oString, ok := o.(string) if !ok { *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) return } buf, err_ := hex.DecodeString(oString) if err_ != nil { *err = err_ return } if len(buf) != length { *err = errors.New(Fmt("Expected bytearray of length %v but got %v", length, len(buf))) return } log.Info("Read bytearray", "bytes", buf) reflect.Copy(rv, reflect.ValueOf(buf)) } else { oSlice, ok := o.([]interface{}) if !ok { *err = errors.New(Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o))) return } if len(oSlice) != length { *err = errors.New(Fmt("Expected array of length %v but got %v", length, len(oSlice))) return } for i := 0; i < length; i++ { elemRv := rv.Index(i) readReflectJSON(elemRv, elemRt, oSlice[i], err) } log.Info(Fmt("Read %v-array", elemRt), "length", length) } case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { // Special case: Byteslices oString, ok := o.(string) if !ok { *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) return } byteslice, err_ := hex.DecodeString(oString) if err_ != nil { *err = err_ return } log.Info("Read byteslice", "bytes", byteslice) rv.Set(reflect.ValueOf(byteslice)) } else { // Read length oSlice, ok := o.([]interface{}) if !ok { *err = errors.New(Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o))) return } length := len(oSlice) log.Info(Fmt("Read length: %v", length)) sliceRv := reflect.MakeSlice(rt, length, length) // Read elems for i := 0; i < length; i++ { elemRv := sliceRv.Index(i) readReflectJSON(elemRv, elemRt, oSlice[i], err) } rv.Set(sliceRv) } case reflect.Struct: if rt == timeType { // Special case: time.Time str, ok := o.(string) if !ok { *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) return } log.Info(Fmt("Read time: %v", str)) t, err_ := time.Parse(iso8601, str) if err_ != nil { *err = err_ return } rv.Set(reflect.ValueOf(t)) } else { oMap, ok := o.(map[string]interface{}) if !ok { *err = errors.New(Fmt("Expected map but got type %v", reflect.TypeOf(o))) return } // TODO: ensure that all fields are set? // TODO: disallow unknown oMap fields? for _, fieldInfo := range typeInfo.Fields { i, fieldType, opts := fieldInfo.unpack() value, ok := oMap[opts.JSONName] if !ok { continue // Skip missing fields. } fieldRv := rv.Field(i) readReflectJSON(fieldRv, fieldType, value, err) } } case reflect.String: str, ok := o.(string) if !ok { *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) return } log.Info(Fmt("Read string: %v", str)) rv.SetString(str) case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: num, ok := o.(float64) if !ok { *err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o))) return } log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: num, ok := o.(float64) if !ok { *err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o))) return } if num < 0 { *err = errors.New(Fmt("Expected unsigned numeric but got %v", num)) return } log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) case reflect.Bool: bl, ok := o.(bool) if !ok { *err = errors.New(Fmt("Expected boolean but got type %v", reflect.TypeOf(o))) return } log.Info(Fmt("Read boolean: %v", bl)) rv.SetBool(bl) default: PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } }
// rv: the reflection value of the thing to write // rt: the type of rv as declared in the container, not necessarily rv.Type(). func writeReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, w io.Writer, n *int64, err *error) { // Get typeInfo typeInfo := GetTypeInfo(rt) if rt.Kind() == reflect.Interface { if rv.IsNil() { // XXX ensure that typeByte 0 is reserved. WriteByte(0x00, w, n, err) return } crv := rv.Elem() // concrete reflection value crt := crv.Type() // concrete reflection type if typeInfo.IsRegisteredInterface { // See if the crt is registered. // If so, we're more restrictive. _, ok := typeInfo.TypeToByte[crt] if !ok { switch crt.Kind() { case reflect.Ptr: *err = errors.New(Fmt("Unexpected pointer type %v for registered interface %v. "+ "Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name())) case reflect.Struct: *err = errors.New(Fmt("Unexpected struct type %v for registered interface %v. "+ "Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name())) default: *err = errors.New(Fmt("Unexpected type %v for registered interface %v. "+ "If this is intentional, please register it.", crt, rt.Name())) } return } } else { // We support writing unsafely for convenience. } // We don't have to write the typeByte here, // the writeReflectBinary() call below will write it. writeReflectBinary(crv, crt, opts, w, n, err) return } if rt.Kind() == reflect.Ptr { // Dereference pointer rv, rt = rv.Elem(), rt.Elem() typeInfo = GetTypeInfo(rt) if !rv.IsValid() { // For better compatibility with other languages, // as far as tendermint/wire is concerned, // pointers to nil values are the same as nil. WriteByte(0x00, w, n, err) return } if typeInfo.Byte == 0x00 { WriteByte(0x01, w, n, err) // continue... } else { // continue... } } // Write type byte if typeInfo.Byte != 0x00 { WriteByte(typeInfo.Byte, w, n, err) } // All other types switch rt.Kind() { case reflect.Array: elemRt := rt.Elem() length := rt.Len() if elemRt.Kind() == reflect.Uint8 { // Special case: Bytearrays if rv.CanAddr() { byteslice := rv.Slice(0, length).Bytes() WriteTo(byteslice, w, n, err) } else { buf := make([]byte, length) reflect.Copy(reflect.ValueOf(buf), rv) WriteTo(buf, w, n, err) } } else { // Write elems for i := 0; i < length; i++ { elemRv := rv.Index(i) writeReflectBinary(elemRv, elemRt, opts, w, n, err) } } case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { // Special case: Byteslices byteslice := rv.Bytes() WriteByteSlice(byteslice, w, n, err) } else { // Write length length := rv.Len() WriteVarint(length, w, n, err) // Write elems for i := 0; i < length; i++ { elemRv := rv.Index(i) writeReflectBinary(elemRv, elemRt, opts, w, n, err) } } case reflect.Struct: if rt == timeType { // Special case: time.Time WriteTime(rv.Interface().(time.Time), w, n, err) } else { for _, fieldInfo := range typeInfo.Fields { i, fieldType, opts := fieldInfo.unpack() fieldRv := rv.Field(i) writeReflectBinary(fieldRv, fieldType, opts, w, n, err) } } case reflect.String: WriteString(rv.String(), w, n, err) case reflect.Int64: if opts.Varint { WriteVarint(int(rv.Int()), w, n, err) } else { WriteInt64(rv.Int(), w, n, err) } case reflect.Int32: WriteInt32(int32(rv.Int()), w, n, err) case reflect.Int16: WriteInt16(int16(rv.Int()), w, n, err) case reflect.Int8: WriteInt8(int8(rv.Int()), w, n, err) case reflect.Int: WriteVarint(int(rv.Int()), w, n, err) case reflect.Uint64: if opts.Varint { WriteUvarint(uint(rv.Uint()), w, n, err) } else { WriteUint64(rv.Uint(), w, n, err) } case reflect.Uint32: WriteUint32(uint32(rv.Uint()), w, n, err) case reflect.Uint16: WriteUint16(uint16(rv.Uint()), w, n, err) case reflect.Uint8: WriteUint8(uint8(rv.Uint()), w, n, err) case reflect.Uint: WriteUvarint(uint(rv.Uint()), w, n, err) case reflect.Bool: if rv.Bool() { WriteUint8(uint8(1), w, n, err) } else { WriteUint8(uint8(0), w, n, err) } default: PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } }
// Contract: Caller must ensure that rt is supported // (e.g. is recursively composed of supported native types, and structs and slices.) func readReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, r io.Reader, n *int64, err *error) { // Get typeInfo typeInfo := GetTypeInfo(rt) if rt.Kind() == reflect.Interface { if !typeInfo.IsRegisteredInterface { // There's no way we can read such a thing. *err = errors.New(Fmt("Cannot read unregistered interface type %v", rt)) return } typeByte := ReadByte(r, n, err) if *err != nil { return } if typeByte == 0x00 { return // nil } crt, ok := typeInfo.ByteToType[typeByte] if !ok { *err = errors.New(Fmt("Unexpected type byte %X for type %v", typeByte, rt)) return } crv := reflect.New(crt).Elem() r = NewPrefixedReader([]byte{typeByte}, r) readReflectBinary(crv, crt, opts, r, n, err) rv.Set(crv) // NOTE: orig rv is ignored. return } if rt.Kind() == reflect.Ptr { typeByte := ReadByte(r, n, err) if *err != nil { return } if typeByte == 0x00 { return // nil } // Create new if rv is nil. if rv.IsNil() { newRv := reflect.New(rt.Elem()) rv.Set(newRv) rv = newRv } // Dereference pointer rv, rt = rv.Elem(), rt.Elem() typeInfo = GetTypeInfo(rt) if typeInfo.Byte != 0x00 { r = NewPrefixedReader([]byte{typeByte}, r) } else if typeByte != 0x01 { *err = errors.New(Fmt("Unexpected type byte %X for ptr of untyped thing", typeByte)) return } // continue... } // Read Byte prefix if typeInfo.Byte != 0x00 { typeByte := ReadByte(r, n, err) if typeByte != typeInfo.Byte { *err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, typeByte)) return } } switch rt.Kind() { case reflect.Array: elemRt := rt.Elem() length := rt.Len() if elemRt.Kind() == reflect.Uint8 { // Special case: Bytearrays buf := make([]byte, length) ReadFull(buf, r, n, err) if *err != nil { return } log.Info("Read bytearray", "bytes", buf) reflect.Copy(rv, reflect.ValueOf(buf)) } else { for i := 0; i < length; i++ { elemRv := rv.Index(i) readReflectBinary(elemRv, elemRt, opts, r, n, err) if *err != nil { return } if MaxBinaryReadSize < *n { *err = ErrBinaryReadSizeOverflow return } } log.Info(Fmt("Read %v-array", elemRt), "length", length) } case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { // Special case: Byteslices byteslice := ReadByteSlice(r, n, err) log.Info("Read byteslice", "bytes", byteslice) rv.Set(reflect.ValueOf(byteslice)) } else { var sliceRv reflect.Value // Read length length := ReadVarint(r, n, err) log.Info(Fmt("Read length: %v", length)) sliceRv = reflect.MakeSlice(rt, 0, 0) // read one ReflectSliceChunk at a time and append for i := 0; i*ReflectSliceChunk < length; i++ { l := MinInt(ReflectSliceChunk, length-i*ReflectSliceChunk) tmpSliceRv := reflect.MakeSlice(rt, l, l) for j := 0; j < l; j++ { elemRv := tmpSliceRv.Index(j) readReflectBinary(elemRv, elemRt, opts, r, n, err) if *err != nil { return } if MaxBinaryReadSize < *n { *err = ErrBinaryReadSizeOverflow return } } sliceRv = reflect.AppendSlice(sliceRv, tmpSliceRv) } rv.Set(sliceRv) } case reflect.Struct: if rt == timeType { // Special case: time.Time t := ReadTime(r, n, err) log.Info(Fmt("Read time: %v", t)) rv.Set(reflect.ValueOf(t)) } else { for _, fieldInfo := range typeInfo.Fields { i, fieldType, opts := fieldInfo.unpack() fieldRv := rv.Field(i) readReflectBinary(fieldRv, fieldType, opts, r, n, err) } } case reflect.String: str := ReadString(r, n, err) log.Info(Fmt("Read string: %v", str)) rv.SetString(str) case reflect.Int64: if opts.Varint { num := ReadVarint(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) } else { num := ReadInt64(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) } case reflect.Int32: num := ReadUint32(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) case reflect.Int16: num := ReadUint16(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) case reflect.Int8: num := ReadUint8(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) case reflect.Int: num := ReadVarint(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetInt(int64(num)) case reflect.Uint64: if opts.Varint { num := ReadVarint(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) } else { num := ReadUint64(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) } case reflect.Uint32: num := ReadUint32(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) case reflect.Uint16: num := ReadUint16(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) case reflect.Uint8: num := ReadUint8(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) case reflect.Uint: num := ReadVarint(r, n, err) log.Info(Fmt("Read num: %v", num)) rv.SetUint(uint64(num)) case reflect.Bool: num := ReadUint8(r, n, err) log.Info(Fmt("Read bool: %v", num)) rv.SetBool(num > 0) default: PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } }
func typeFromType(t reflect.Type) (Type, error) { // Hack workaround for https://golang.org/issue/3853. // This explicit check should not be necessary. if t == byteType { return PredeclaredType("byte"), nil } if imp := t.PkgPath(); imp != "" { return &NamedType{ Package: imp, Type: t.Name(), }, nil } // only unnamed or predeclared types after here // Lots of types have element types. Let's do the parsing and error checking for all of them. var elemType Type switch t.Kind() { case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice: var err error elemType, err = typeFromType(t.Elem()) if err != nil { return nil, err } } switch t.Kind() { case reflect.Array: return &ArrayType{ Len: t.Len(), Type: elemType, }, nil case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.String: return PredeclaredType(t.Kind().String()), nil case reflect.Chan: var dir ChanDir switch t.ChanDir() { case reflect.RecvDir: dir = RecvDir case reflect.SendDir: dir = SendDir } return &ChanType{ Dir: dir, Type: elemType, }, nil case reflect.Func: in, variadic, out, err := funcArgsFromType(t) if err != nil { return nil, err } return &FuncType{ In: in, Out: out, Variadic: variadic, }, nil case reflect.Interface: // Two special interfaces. if t.NumMethod() == 0 { return PredeclaredType("interface{}"), nil } if t == errorType { return PredeclaredType("error"), nil } case reflect.Map: kt, err := typeFromType(t.Key()) if err != nil { return nil, err } return &MapType{ Key: kt, Value: elemType, }, nil case reflect.Ptr: return &PointerType{ Type: elemType, }, nil case reflect.Slice: return &ArrayType{ Len: -1, Type: elemType, }, nil case reflect.Struct: if t.NumField() == 0 { return PredeclaredType("struct{}"), nil } } // TODO: Struct, UnsafePointer return nil, fmt.Errorf("can't yet turn %v (%v) into a model.Type", t, t.Kind()) }
func new_dataTypeFromType(t reflect.Type) *DataType { var dt *DataType = nil switch t.Kind() { case reflect.Int: dt = T_NATIVE_INT // FIXME: .Copy() instead ? case reflect.Int8: dt = T_NATIVE_INT8 case reflect.Int16: dt = T_NATIVE_INT16 case reflect.Int32: dt = T_NATIVE_INT32 case reflect.Int64: dt = T_NATIVE_INT64 case reflect.Uint: dt = T_NATIVE_UINT // FIXME: .Copy() instead ? case reflect.Uint8: dt = T_NATIVE_UINT8 case reflect.Uint16: dt = T_NATIVE_UINT16 case reflect.Uint32: dt = T_NATIVE_UINT32 case reflect.Uint64: dt = T_NATIVE_UINT64 case reflect.Float32: dt = T_NATIVE_FLOAT case reflect.Float64: dt = T_NATIVE_DOUBLE case reflect.String: dt = T_GO_STRING //dt = T_C_S1 case reflect.Array: elem_type := new_dataTypeFromType(t.Elem()) n := t.Len() dims := []int{n} adt, err := NewArrayType(elem_type, dims) if err != nil { panic(err) } dt, err = adt.Copy() if err != nil { panic(err) } case reflect.Slice: elem_type := new_dataTypeFromType(t.Elem()) vlen_dt, err := NewVarLenType(elem_type) if err != nil { panic(err) } dt, err = vlen_dt.Copy() if err != nil { panic(err) } case reflect.Struct: sz := int(t.Size()) hdf_dt, err := CreateDataType(T_COMPOUND, sz) if err != nil { panic(err) } cdt := &CompType{*hdf_dt} n := t.NumField() for i := 0; i < n; i++ { f := t.Field(i) var field_dt *DataType = nil field_dt = new_dataTypeFromType(f.Type) offset := int(f.Offset + 0) if field_dt == nil { panic(fmt.Sprintf("pb with field [%d-%s]", i, f.Name)) } field_name := string(f.Tag) if len(field_name) == 0 { field_name = f.Name } err = cdt.Insert(field_name, offset, field_dt) if err != nil { panic(fmt.Sprintf("pb with field [%d-%s]: %s", i, f.Name, err)) } } cdt.Lock() dt, err = cdt.Copy() if err != nil { panic(err) } case reflect.Ptr: panic("sorry, pointers not yet supported") default: panic(fmt.Sprintf("unhandled kind (%d)", t.Kind())) } return dt }
func ctype_from_gotype(rt reflect.Type) Type { var t Type switch rt.Kind() { case reflect.Int: t = C_int case reflect.Int8: t = C_int8 case reflect.Int16: t = C_int16 case reflect.Int32: t = C_int32 case reflect.Int64: t = C_int64 case reflect.Uint: t = C_uint case reflect.Uint8: t = C_uint8 case reflect.Uint16: t = C_uint16 case reflect.Uint32: t = C_uint32 case reflect.Uint64: t = C_uint64 case reflect.Float32: t = C_float case reflect.Float64: t = C_double case reflect.Array: et := ctype_from_gotype(rt.Elem()) ct, err := NewArrayType(rt.Len(), et) if err != nil { panic("ffi: " + err.Error()) } ct.set_gotype(rt) t = ct case reflect.Ptr: et := ctype_from_gotype(rt.Elem()) ct, err := NewPointerType(et) if err != nil { panic("ffi: " + err.Error()) } t = ct case reflect.Slice: et := ctype_from_gotype(rt.Elem()) ct, err := NewSliceType(et) if err != nil { panic("ffi: " + err.Error()) } ct.set_gotype(rt) t = ct case reflect.Struct: fields := make([]Field, rt.NumField()) for i := 0; i < rt.NumField(); i++ { field := rt.Field(i) fields[i] = Field{ Name: field.Name, Type: ctype_from_gotype(field.Type), } } ct, err := NewStructType(rt.Name(), fields) if err != nil { panic("ffi: " + err.Error()) } ct.set_gotype(rt) t = ct case reflect.String: panic("unimplemented") default: panic("unhandled kind [" + rt.Kind().String() + "]") } return t }
// TypeFromNative converts a regular Go type into a the corresponding // interpreter Type. func TypeFromNative(t reflect.Type) Type { if et, ok := evalTypes[t]; ok { return et } var nt *NamedType if t.Name() != "" { name := t.PkgPath() + "·" + t.Name() nt = &NamedType{token.Position{}, name, nil, true, make(map[string]Method)} evalTypes[t] = nt } var et Type switch t := t.(type) { case *reflect.BoolType: et = BoolType case *reflect.FloatType: switch t.Kind() { case reflect.Float32: et = Float32Type case reflect.Float64: et = Float64Type case reflect.Float: et = FloatType } case *reflect.IntType: switch t.Kind() { case reflect.Int16: et = Int16Type case reflect.Int32: et = Int32Type case reflect.Int64: et = Int64Type case reflect.Int8: et = Int8Type case reflect.Int: et = IntType } case *reflect.UintType: switch t.Kind() { case reflect.Uint16: et = Uint16Type case reflect.Uint32: et = Uint32Type case reflect.Uint64: et = Uint64Type case reflect.Uint8: et = Uint8Type case reflect.Uint: et = UintType case reflect.Uintptr: et = UintptrType } case *reflect.StringType: et = StringType case *reflect.ArrayType: et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem())) case *reflect.ChanType: log.Panicf("%T not implemented", t) case *reflect.FuncType: nin := t.NumIn() // Variadic functions have DotDotDotType at the end variadic := t.DotDotDot() if variadic { nin-- } in := make([]Type, nin) for i := range in { in[i] = TypeFromNative(t.In(i)) } out := make([]Type, t.NumOut()) for i := range out { out[i] = TypeFromNative(t.Out(i)) } et = NewFuncType(in, variadic, out) case *reflect.InterfaceType: log.Panicf("%T not implemented", t) case *reflect.MapType: log.Panicf("%T not implemented", t) case *reflect.PtrType: et = NewPtrType(TypeFromNative(t.Elem())) case *reflect.SliceType: et = NewSliceType(TypeFromNative(t.Elem())) case *reflect.StructType: n := t.NumField() fields := make([]StructField, n) for i := 0; i < n; i++ { sf := t.Field(i) // TODO(austin) What to do about private fields? fields[i].Name = sf.Name fields[i].Type = TypeFromNative(sf.Type) fields[i].Anonymous = sf.Anonymous } et = NewStructType(fields) case *reflect.UnsafePointerType: log.Panicf("%T not implemented", t) default: log.Panicf("unexpected reflect.Type: %T", t) } if nt != nil { if _, ok := et.(*NamedType); !ok { nt.Complete(et) et = nt } } nativeTypes[et] = t evalTypes[t] = et return et }
func writeType(buf *bytes.Buffer, ptrs int, t reflect.Type) { parens := ptrs > 0 switch t.Kind() { case reflect.Chan, reflect.Func, reflect.UnsafePointer: parens = true } if parens { buf.WriteRune('(') for i := 0; i < ptrs; i++ { buf.WriteRune('*') } } switch t.Kind() { case reflect.Ptr: if ptrs == 0 { // This pointer was referenced from within writeType (e.g., as part of // rendering a list), and so hasn't had its pointer asterisk accounted // for. buf.WriteRune('*') } writeType(buf, 0, t.Elem()) case reflect.Interface: if n := t.Name(); n != "" { buf.WriteString(t.String()) } else { buf.WriteString("interface{}") } case reflect.Array: buf.WriteRune('[') buf.WriteString(strconv.FormatInt(int64(t.Len()), 10)) buf.WriteRune(']') writeType(buf, 0, t.Elem()) case reflect.Slice: if t == reflect.SliceOf(t.Elem()) { buf.WriteString("[]") writeType(buf, 0, t.Elem()) } else { // Custom slice type, use type name. buf.WriteString(t.String()) } case reflect.Map: if t == reflect.MapOf(t.Key(), t.Elem()) { buf.WriteString("map[") writeType(buf, 0, t.Key()) buf.WriteRune(']') writeType(buf, 0, t.Elem()) } else { // Custom map type, use type name. buf.WriteString(t.String()) } default: buf.WriteString(t.String()) } if parens { buf.WriteRune(')') } }