예제 #1
0
// Pretty-print any random data we get back from the server
func genericLogData(name string, v reflect.Value, indent string, skip int) {
	prefix := "->" + indent
	if name != "" {
		prefix = "-> " + indent + name + ":"
	}

	// For pointers and interfaces, just grab the underlying value and try again
	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		genericLogData(name, v.Elem(), indent, skip)
		return
	}

	// Only print if skip is 0.  Recursive calls should indent or decrement skip, depending on if anything was
	// printed.
	var skipped bool
	if skip == 0 {
		skipped = false
		indent = indent + "  "
	} else {
		skipped = true
		skip = skip - 1
	}

	switch v.Kind() {
	case reflect.Struct:
		if !skipped {
			Log("%s\n", prefix)
		}
		for f := 0; f < v.NumField(); f++ {
			name := v.Type().Field(f).Name
			genericLogData(name, v.Field(f), indent, skip)
		}
	case reflect.Array:
		fallthrough
	case reflect.Slice:
		if !skipped {
			Log("%s\n", prefix)
		}
		for i := 0; i < v.Len(); i++ {
			genericLogData("", v.Index(i), indent, skip)
		}
	case reflect.Map:
		if !skipped {
			Log("%s\n", prefix)
		}
		for _, k := range v.MapKeys() {
			if name, ok := k.Interface().(string); ok {
				genericLogData(name, v.MapIndex(k), indent, skip)
			} else {
				genericLogData("Unknown field", v.MapIndex(k), indent, skip)
			}
		}
	default:
		if v.CanInterface() {
			Log("%s %v", prefix, v.Interface())
		} else {
			Log("%s <Invalid>", prefix)
		}
	}
}
예제 #2
0
파일: golf.go 프로젝트: akutz/golf
func isValueKind(v *reflect.Value, isEmpty *bool, val *interface{}) bool {
	switch v.Kind() {
	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:
		if val != nil && v.CanInterface() {
			*val = v.Interface()
		}
		if isEmpty != nil {
			*isEmpty = false
		}
		return true
	}
	return false
}
예제 #3
0
파일: vm.go 프로젝트: postfix/anko
// equal return true when lhsV and rhsV is same value.
func equal(lhsV, rhsV reflect.Value) bool {
	lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV)
	if lhsIsNil && rhsIsNil {
		return true
	}
	if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) {
		return false
	}
	if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr {
		lhsV = lhsV.Elem()
	}
	if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr {
		rhsV = rhsV.Elem()
	}
	if !lhsV.IsValid() || !rhsV.IsValid() {
		return true
	}
	if isNum(lhsV) && isNum(rhsV) {
		if rhsV.Type().ConvertibleTo(lhsV.Type()) {
			rhsV = rhsV.Convert(lhsV.Type())
		}
	}
	if lhsV.CanInterface() && rhsV.CanInterface() {
		return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface())
	}
	return reflect.DeepEqual(lhsV, rhsV)
}
예제 #4
0
파일: print.go 프로젝트: sreis/go
// printValue is like printArg but starts with a reflect value, not an interface{} value.
func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
	if !value.IsValid() {
		switch verb {
		case 'T', 'v':
			p.buf.WriteString(nilAngleString)
		default:
			p.badVerb(verb)
		}
		return
	}

	// Special processing considerations.
	// %T (the value's type) and %p (its address) are special; we always do them first.
	switch verb {
	case 'T':
		p.printArg(value.Type().String(), 's', 0)
		return
	case 'p':
		p.fmtPointer(value, verb)
		return
	}

	// Handle values with special methods.
	// Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us.
	p.arg = nil // Make sure it's cleared, for safety.
	if value.CanInterface() {
		p.arg = value.Interface()
	}
	if p.handleMethods(verb, depth) {
		return
	}

	p.printReflectValue(value, verb, depth)
}
예제 #5
0
func (vk *GenericInvoker) Return(f interface{}, returns []interface{}) ([]interface{}, error) {
	funcT := reflect.TypeOf(f)

	// make sure parameter matched
	if len(returns) != funcT.NumOut() {
		return nil, fmt.Errorf("Parameter Count mismatch: %v %v", len(returns), funcT.NumOut())
	}

	var (
		err error
		ret reflect.Value
	)

	out := make([]interface{}, funcT.NumOut())
	for i := 0; i < funcT.NumOut(); i++ {
		ret, err = vk.from(returns[i], funcT.Out(i))
		if err != nil {
			return nil, err
		}
		if ret.CanInterface() {
			out[i] = ret.Interface()
		} else {
			return nil, fmt.Errorf("Unable to convert to interface{} for %d", i)
		}
	}

	return out, nil
}
예제 #6
0
파일: encode.go 프로젝트: gunosy/dynamo
// thanks James Henstridge
// TODO: tweak
// TODO: IsZero() interface support
func isZero(rv reflect.Value) bool {
	// use IsZero for supported types
	if rv.CanInterface() {
		if zeroer, ok := rv.Interface().(isZeroer); ok {
			return zeroer.IsZero()
		}
	}

	switch rv.Kind() {
	case reflect.Func, reflect.Map, reflect.Slice:
		return rv.IsNil()
	case reflect.Array:
		z := true
		for i := 0; i < rv.Len(); i++ {
			z = z && isZero(rv.Index(i))
		}
		return z
	case reflect.Struct:
		z := true
		for i := 0; i < rv.NumField(); i++ {
			z = z && isZero(rv.Field(i))
		}
		return z
	}
	// Compare other types directly:
	z := reflect.Zero(rv.Type())
	return rv.Interface() == z.Interface()
}
예제 #7
0
파일: decode.go 프로젝트: ebml-go/ebml-go
func setFieldDefaults(v reflect.Value, sf reflect.StructField, s reflect.Value) {
	if v.CanInterface() && reflect.DeepEqual(
		v.Interface(), reflect.Zero(v.Type()).Interface()) {
		tag := sf.Tag.Get("ebmldef")
		if tag != "" {
			switch v.Kind() {
			case reflect.Int, reflect.Int64:
				u, _ := strconv.ParseInt(tag, 10, 0)
				v.SetInt(int64(u))
			case reflect.Uint, reflect.Uint64:
				u, _ := strconv.ParseUint(tag, 10, 0)
				v.SetUint(u)
			case reflect.Float32, reflect.Float64:
				f, _ := strconv.ParseFloat(tag, 64)
				v.SetFloat(f)
			case reflect.String:
				v.SetString(tag)
			default:
				log.Panic("Unsupported default value")
			}
		}
		ltag := sf.Tag.Get("ebmldeflink")
		if ltag != "" {
			v.Set(s.FieldByName(ltag))
		}
	}
}
예제 #8
0
파일: csvutil.go 프로젝트: rzajac/csvutil
// ToCsv takes a struct and returns CSV line with data delimited by delim and
// true, false values translated to boolTrue, boolFalse respectively.
func ToCsv(v interface{}, delim, boolTrue, boolFalse string) string {
	var csvLine []string
	var strValue string
	var structField reflect.StructField
	var field reflect.Value

	t := reflect.ValueOf(v)

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if t.Kind() != reflect.Struct {
		panic("Expected pointer to a struct")
	}

	for i := 0; i < t.NumField(); i++ {
		structField = t.Type().Field(i)
		field = t.Field(i)

		if structField.Anonymous {
			strValue = ToCsv(field.Interface(), delim, boolTrue, boolFalse)
			csvLine = append(csvLine, strValue)
			continue
		}

		if !skip(structField.Tag) && field.CanInterface() {
			strValue = getValue(field, boolTrue, boolFalse)
			csvLine = append(csvLine, strValue)
		}
	}

	return strings.Join(csvLine, delim)
}
예제 #9
0
파일: read.go 프로젝트: hurkgu/go
// unmarshalAttr unmarshals a single XML attribute into val.
func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
	if val.Kind() == reflect.Ptr {
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}
		val = val.Elem()
	}
	if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
		// This is an unmarshaler with a non-pointer receiver,
		// so it's likely to be incorrect, but we do what we're told.
		return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
	}
	if val.CanAddr() {
		pv := val.Addr()
		if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
			return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
		}
	}

	// Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
	if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
		// This is an unmarshaler with a non-pointer receiver,
		// so it's likely to be incorrect, but we do what we're told.
		return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
	}
	if val.CanAddr() {
		pv := val.Addr()
		if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
			return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
		}
	}
	return copyValue(val, []byte(attr.Value))
}
예제 #10
0
파일: deepequal.go 프로젝트: juju/testing
// bypassCanInterface returns a version of v that
// bypasses the CanInterface check.
func bypassCanInterface(v reflect.Value) reflect.Value {
	if !v.IsValid() || v.CanInterface() {
		return v
	}
	*flagField(&v) &^= flagRO
	return v
}
예제 #11
0
func isZeroVal(val reflect.Value) bool {
	if !val.CanInterface() {
		return false
	}
	z := reflect.Zero(val.Type()).Interface()
	return reflect.DeepEqual(val.Interface(), z)
}
예제 #12
0
// IsZero returns true when the value is a zero for the type
func isZero(data reflect.Value) bool {
	if !data.CanInterface() {
		return true
	}
	tpe := data.Type()
	return reflect.DeepEqual(data.Interface(), reflect.Zero(tpe).Interface())
}
예제 #13
0
파일: print.go 프로젝트: varialus/godfly
// printValue is like printArg but starts with a reflect value, not an interface{} value.
func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
	if !value.IsValid() {
		if verb == 'T' || verb == 'v' {
			p.buf.Write(nilAngleBytes)
		} else {
			p.badVerb(verb)
		}
		return false
	}

	// Special processing considerations.
	// %T (the value's type) and %p (its address) are special; we always do them first.
	switch verb {
	case 'T':
		p.printArg(value.Type().String(), 's', false, false, 0)
		return false
	case 'p':
		p.fmtPointer(value, verb, goSyntax)
		return false
	}

	// Handle values with special methods.
	// Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us.
	p.arg = nil // Make sure it's cleared, for safety.
	if value.CanInterface() {
		p.arg = value.Interface()
	}
	if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
		return isString
	}

	return p.printReflectValue(value, verb, plus, goSyntax, depth)
}
예제 #14
0
파일: log.go 프로젝트: mousesun/log
func printValue(v reflect.Value, space int) {
	if !v.CanInterface() {
		fmt.Print(v)
	} else {
		printVar(v.Interface(), space)
	}
}
func formatValue(value reflect.Value, indentation uint) string {
	if indentation > MaxDepth {
		return "..."
	}

	if isNilValue(value) {
		return "nil"
	}

	if UseStringerRepresentation {
		if value.CanInterface() {
			obj := value.Interface()
			switch x := obj.(type) {
			case fmt.GoStringer:
				return x.GoString()
			case fmt.Stringer:
				return x.String()
			}
		}
	}

	switch value.Kind() {
	case reflect.Bool:
		return fmt.Sprintf("%v", value.Bool())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return fmt.Sprintf("%v", value.Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return fmt.Sprintf("%v", value.Uint())
	case reflect.Uintptr:
		return fmt.Sprintf("0x%x", value.Uint())
	case reflect.Float32, reflect.Float64:
		return fmt.Sprintf("%v", value.Float())
	case reflect.Complex64, reflect.Complex128:
		return fmt.Sprintf("%v", value.Complex())
	case reflect.Chan:
		return fmt.Sprintf("0x%x", value.Pointer())
	case reflect.Func:
		return fmt.Sprintf("0x%x", value.Pointer())
	case reflect.Ptr:
		return formatValue(value.Elem(), indentation)
	case reflect.Slice:
		return formatSlice(value, indentation)
	case reflect.String:
		return formatString(value.String(), indentation)
	case reflect.Array:
		return formatSlice(value, indentation)
	case reflect.Map:
		return formatMap(value, indentation)
	case reflect.Struct:
		return formatStruct(value, indentation)
	case reflect.Interface:
		return formatValue(value.Elem(), indentation)
	default:
		if value.CanInterface() {
			return fmt.Sprintf("%#v", value.Interface())
		} else {
			return fmt.Sprintf("%#v", value)
		}
	}
}
예제 #16
0
func quietOutput(prefix string, v reflect.Value) {
	// For pointers and interfaces, just grab the underlying value and try again
	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		quietOutput(prefix, v.Elem())
		return
	}

	switch v.Kind() {
	case reflect.Struct:
		for f := 0; f < v.NumField(); f++ {
			name := v.Type().Field(f).Name
			quietOutput(prefix+name+" ", v.Field(f))
		}
	case reflect.Array:
		fallthrough
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			quietOutput(prefix, v.Index(i))
		}
	case reflect.Map:
		for _, k := range v.MapKeys() {
			if name, ok := k.Interface().(string); ok {
				quietOutput(prefix+name+" ", v.MapIndex(k))
			} else {
				quietOutput(prefix+"UnknownField", v.MapIndex(k))
			}
		}
	default:
		if v.CanInterface() {
			fmt.Printf("%s%v\n", prefix, v.Interface())
		} else {
			fmt.Printf("%s <Invalid>", prefix)
		}
	}
}
예제 #17
0
// layerString outputs, recursively, a layer in a "smart" way.  See docs for
// LayerString for more details.
//
// Params:
//   i - value to write out
//   anonymous:  if we're currently recursing an anonymous member of a struct
//   writeSpace:  if we've already written a value in a struct, and need to
//     write a space before writing more.  This happens when we write various
//     anonymous values, and need to keep writing more.
func layerString(v reflect.Value, anonymous bool, writeSpace bool) string {
	// Let String() functions take precedence.
	if v.CanInterface() {
		if s, ok := v.Interface().(fmt.Stringer); ok {
			return s.String()
		}
	}
	// Reflect, and spit out all the exported fields as key=value.
	switch v.Type().Kind() {
	case reflect.Interface, reflect.Ptr:
		if v.IsNil() {
			return "nil"
		}
		r := v.Elem()
		return layerString(r, anonymous, writeSpace)
	case reflect.Struct:
		var b bytes.Buffer
		typ := v.Type()
		if !anonymous {
			b.WriteByte('{')
		}
		for i := 0; i < v.NumField(); i++ {
			// Check if this is upper-case.
			ftype := typ.Field(i)
			f := v.Field(i)
			if ftype.Anonymous {
				anonStr := layerString(f, true, writeSpace)
				writeSpace = writeSpace || anonStr != ""
				b.WriteString(anonStr)
			} else if ftype.PkgPath == "" { // exported
				if writeSpace {
					b.WriteByte(' ')
				}
				writeSpace = true
				fmt.Fprintf(&b, "%s=%s", typ.Field(i).Name, layerString(f, false, writeSpace))
			}
		}
		if !anonymous {
			b.WriteByte('}')
		}
		return b.String()
	case reflect.Slice:
		var b bytes.Buffer
		b.WriteByte('[')
		if v.Len() > 4 {
			fmt.Fprintf(&b, "..%d..", v.Len())
		} else {
			for j := 0; j < v.Len(); j++ {
				if j != 0 {
					b.WriteString(", ")
				}
				b.WriteString(layerString(v.Index(j), false, false))
			}
		}
		b.WriteByte(']')
		return b.String()
	}
	return fmt.Sprintf("%v", v.Interface())
}
예제 #18
0
파일: schema.go 프로젝트: lacework/go-avro
// Checks whether the given value is writeable to this schema.
func (rs *RecordSchema) Validate(v reflect.Value) bool {
	v = dereference(v)
	if v.Kind() != reflect.Struct || !v.CanAddr() || !v.CanInterface() {
		fmt.Println("Incorrect record structure")
		return false
	}
	rec, ok := v.Interface().(GenericRecord)
	if !ok {
		// This is not a generic record and is likely a specific record. Hence
		// use the basic check.
		panic("Not supported")
		return v.Kind() == reflect.Struct
	}
	// If lengths for value and schema does not match up, then validate will fail
	if len(rs.Fields) != len(rec.fields) {
		return false
	}
	// Cache names in a map
	if rs.mapFields == nil {
		rs.mapFields = make(map[string]int)
		for idx := range rs.Fields {
			rs.mapFields[rs.Fields[idx].Name] = idx
		}
	}

	field_count := 0
	for key, val := range rec.fields {
		// Implement a fast path. If all names of the fields match up, we assume schemas will match too.
		// This may not be true in general, but in our case it is, and recursively validating fields is
		// very expensive.
		if _, ok := rs.mapFields[key]; ok {
			field_count++
			continue
		} else {
			break
		}
		for idx := range rs.Fields {
			// key.Name must have rs.Fields[idx].Name as a suffix
			if len(rs.Fields[idx].Name) <= len(key) {
				lhs := key[len(key)-len(rs.Fields[idx].Name) : len(key)]
				if lhs == rs.Fields[idx].Name {
					if !rs.Fields[idx].Type.Validate(reflect.ValueOf(val)) {
						fmt.Println("field validation failed ..", lhs, "..", rs.GetName())
						return false
					}
					field_count++
					break
				}
			}
		}
	}

	// All of the fields set must be accounted for in the union.
	if field_count < len(rec.fields) {
		return false
	}

	return true
}
예제 #19
0
파일: formatter.go 프로젝트: revantk/pretty
func getFormatterInterface(v reflect.Value) (f fmt.Formatter, ok bool) {
	ok = v.CanInterface()
	if !ok {
		return
	}
	f, ok = v.Interface().(fmt.Formatter)
	return
}
예제 #20
0
func rvToExpr(rv reflect.Value) ast.Expr {
	if rv.CanInterface() {
		if e, ok := rv.Interface().(ast.Expr); ok {
			return e
		}
	}
	return nil
}
예제 #21
0
파일: common.go 프로젝트: rcrowley/go-goon
// handleMethods attempts to call the Error and String methods on the underlying
// type the passed reflect.Value represents and outputes the result to Writer w.
//
// It handles panics in any called methods by catching and displaying the error
// as the formatted value.
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
	// We need an interface to check if the type implements the error or
	// Stringer interface.  However, the reflect package won't give us an
	// interface on certain things like unexported struct fields in order
	// to enforce visibility rules.  We use unsafe to bypass these restrictions
	// since this package does not mutate the values.
	if !v.CanInterface() {
		v = unsafeReflectValue(v)
	}

	// Choose whether or not to do error and Stringer interface lookups against
	// the base type or a pointer to the base type depending on settings.
	// Technically calling one of these methods with a pointer receiver can
	// mutate the value, however, types which choose to satisify an error or
	// Stringer interface with a pointer receiver should not be mutating their
	// state inside these interface methods.
	var viface interface{}
	if !cs.DisablePointerMethods {
		if !v.CanAddr() {
			v = unsafeReflectValue(v)
		}
		viface = v.Addr().Interface()
	} else {
		if v.CanAddr() {
			v = v.Addr()
		}
		viface = v.Interface()
	}

	// Is it an error or Stringer?
	switch iface := viface.(type) {
	case error:
		defer catchPanic(w, v)
		if cs.ContinueOnMethod {
			w.Write(openParenBytes)
			w.Write([]byte(iface.Error()))
			w.Write(closeParenBytes)
			w.Write(spaceBytes)
			return false
		}

		w.Write([]byte(iface.Error()))
		return true

	case fmt.Stringer:
		defer catchPanic(w, v)
		if cs.ContinueOnMethod {
			w.Write(openParenBytes)
			w.Write([]byte(iface.String()))
			w.Write(closeParenBytes)
			w.Write(spaceBytes)
			return false
		}
		w.Write([]byte(iface.String()))
		return true
	}
	return false
}
예제 #22
0
//only cacheable values will be inspected at attribute level and, perhaps, stored separately.
//non cacheable values, will be stored at all
func addIfCacheable(values *[]reflect.Value, value reflect.Value) {
	if value.IsValid() && value.CanInterface() {
		// i really try to put these two ifs at the same line... sorry about that :-(
		if cacheable, isCacheable := value.Interface().(Cacheable); isCacheable && len(cacheable.GetCacheKey()) > 0 {
			//the value is cacheable and key is not empty
			*values = append(*values, value)
		}
	}
}
예제 #23
0
파일: copy.go 프로젝트: otm/nagu
func isReadableReader(src reflect.Value) bool {
	if !(src.CanInterface()) {
		return false
	}
	if _, ok := src.Interface().(io.Reader); ok {
		return true
	}
	return false
}
예제 #24
0
파일: pretty.go 프로젝트: mrlauer/go-pretty
func pretty(v reflect.Value, indent string) string {

	var result string

	// If it's a Stringer, and we can get to it, use that
	if v.CanInterface() {
		if s, ok := v.Interface().(fmt.Stringer); ok {
			return s.String()
		}
	}

	switch v.Kind() {
	case reflect.Interface:
		if v.IsNil() {
			return "nil"
		}
		return pretty(v.Elem(), indent)
	case reflect.Slice:
		fallthrough
	case reflect.Array:
		n := v.Len()
		result = fmt.Sprintf("[%d]%s[\n", n, v.Type().Elem())
		for i := 0; i < n; i++ {
			f := pretty(v.Index(i), indent)
			result += indent + addIndent(f, indent) + "\n"
		}
		result += "]"
		return result
	case reflect.Ptr:
		if v.IsNil() {
			return "nil"
		}
		return fmt.Sprintf("&%s", pretty(v.Elem(), indent))
	case reflect.Struct:
		n := v.NumField()
		result = fmt.Sprintf("%v{\n", v.Type())
		for i := 0; i < n; i++ {
			sf := v.Type().Field(i)
			f := pretty(v.Field(i), indent)
			result += fmt.Sprintf("%s%s: %s\n", indent, sf.Name, addIndent(f, indent))
		}
		result += "}"
	case reflect.Map:
		result = fmt.Sprintf("map[%s]%s[\n", v.Type().Key(), v.Type().Elem())
		keys := v.MapKeys()
		for _, k := range keys {
			e := v.MapIndex(k)
			keyStr := addIndent(pretty(k, indent), indent)
			elemStr := addIndent(pretty(e, indent), indent)
			result += fmt.Sprintf("%s%s: %s\n", indent, keyStr, elemStr)
		}
		result += "]"
	default:
		result = fmt.Sprintf("%v", getInterfaceDammit(v))
	}
	return result
}
예제 #25
0
/*
func (handler *JsonHttpHandler) rpcCall(funcMeta *ApiFuncMeta, rawInput *httpInput) (interface{}, error) {
	if handler.ReflectDecl == nil {
		return structRpcCall(funcMeta, rawInput)
	}
	objectReflectType := funcMeta.AttachObject.Type()
	f, ok := handler.ReflectDecl.GetMethodDeclByReflectType(objectReflectType, funcMeta.MethodName)
	if !ok {
		return nil, fmt.Errorf("not found method in ReflectDecl %s.%s", objectReflectType.Name(), funcMeta.MethodName)
	}
	reflectFuncDecl, err := f.GetReflectFuncDecl(funcMeta.Func.Type(), funcMeta.IsMethod)
	if err != nil {
		return nil, fmt.Errorf("func %s.%s FuncDecl not match reflect err:%s", objectReflectType.Name(), funcMeta.MethodName, err.Error())
	}
	if len(reflectFuncDecl.Results) > 0 && !reflectFuncDecl.ResultHasNames {
		return nil, fmt.Errorf("func %s.%s need have result name to become a api func", objectReflectType.Name(), funcMeta.MethodName)
	}
	inValues := make([]reflect.Value, funcMeta.Func.Type().NumIn())
	if funcMeta.IsMethod {
		inValues[0] = funcMeta.AttachObject
	}
	if len(reflectFuncDecl.Params) > 0 {
		inRaw := map[string]json.RawMessage{}
		err := json.Unmarshal([]byte(rawInput.Data), inRaw)
		if err != nil {
			return nil, fmt.Errorf("api input shuold be a map :%s", err.Error())
		}
		for key, rawData := range inRaw {
			field, ok := reflectFuncDecl.ParamMap[key]
			if !ok {
				continue
			}
			thisValuePtr := reflect.New(field.Type)
			err := json.Unmarshal([]byte(rawData), thisValuePtr.Interface())
			if err != nil {
				return nil, fmt.Errorf("api input key: %s, type not match: %s", key, err.Error())
			}
			inValues[field.Index] = thisValuePtr.Elem()
		}
		//zero value input for key not in ParamMap
		for i, value := range inValues {
			if value.IsValid() {
				continue
			}
			inValues[i] = reflect.Zero(funcMeta.Func.Type().In(i))
		}
	}
	return nil, errors.New("not implement rpcCall by function param name")
}
*/
func structRpcCall(funcMeta *ApiFuncMeta, rawInput *httpInput) (interface{}, error) {
	funcType := funcMeta.Func.Type()
	var inValues []reflect.Value
	var apiOutputValue reflect.Value
	serviceValue := funcMeta.AttachObject
	switch funcType.NumIn() {
	case 1:
		inValues = []reflect.Value{serviceValue}
	case 2:
		apiInputValue, err := jsonUnmarshalFromPtrReflectType(funcType.In(1), []byte(rawInput.Data))
		if err != nil {
			return nil, err
		}
		inValues = []reflect.Value{serviceValue, apiInputValue}
	case 3:
		apiInputValue, err := jsonUnmarshalFromPtrReflectType(funcType.In(1), []byte(rawInput.Data))
		if err != nil {
			return nil, err
		}
		apiOutputValue = reflect.New(funcType.In(2).Elem())
		inValues = []reflect.Value{serviceValue, apiInputValue, apiOutputValue}
	default:
		return nil, &ApiFuncArgumentError{Reason: "only accept function input argument num 0,1,2", ApiName: rawInput.Name}
	}
	switch funcType.NumOut() {
	case 0:
	case 1:
		if funcType.Out(0).Kind() != reflect.Interface {
			return nil, &ApiFuncArgumentError{
				Reason:  "only accept function output one argument with error",
				ApiName: rawInput.Name,
			}
		}
	default:
		return nil, &ApiFuncArgumentError{Reason: "only accept function output argument num 0,1", ApiName: rawInput.Name}
	}
	outValues := funcMeta.Func.Call(inValues)
	var output interface{}
	if apiOutputValue.IsValid() && apiOutputValue.CanInterface() {
		output = apiOutputValue.Interface()
	}
	if len(outValues) == 1 {
		if outValues[0].IsNil() {
			return output, nil
		}
		err, ok := outValues[0].Interface().(error)
		if ok == false {
			return nil, &ApiFuncArgumentError{
				Reason:  "only accept function output one argument with error",
				ApiName: rawInput.Name,
			}
		}
		return nil, err
	}
	return output, nil
}
예제 #26
0
func convertMarshal(val reflect.Value) (bool, string, error) {
	// Check first for the Marshaler interface
	if val.Type().NumMethod() > 0 && val.CanInterface() {
		if marshaler, ok := val.Interface().(Marshaler); ok {
			ret, err := marshaler.MarshalFlag()
			return true, ret, err
		}
	}

	return false, "", nil
}
예제 #27
0
// if this value is a Locker, lock it and add it to the locks slice
func (w *walker) lock(v reflect.Value) {
	if !w.useLocks {
		return
	}

	if !v.IsValid() || !v.CanInterface() {
		return
	}

	type rlocker interface {
		RLocker() sync.Locker
	}

	var locker sync.Locker

	// We can't call Interface() on a value directly, since that requires
	// a copy. This is OK, since the pointer to a value which is a sync.Locker
	// is also a sync.Locker.
	if v.Kind() == reflect.Ptr {
		switch l := v.Interface().(type) {
		case rlocker:
			// don't lock a mutex directly
			if _, ok := l.(*sync.RWMutex); !ok {
				locker = l.RLocker()
			}
		case sync.Locker:
			locker = l
		}
	} else if v.CanAddr() {
		switch l := v.Addr().Interface().(type) {
		case rlocker:
			// don't lock a mutex directly
			if _, ok := l.(*sync.RWMutex); !ok {
				locker = l.RLocker()
			}
		case sync.Locker:
			locker = l
		}
	}

	// still no callable locker
	if locker == nil {
		return
	}

	// don't lock a mutex directly
	switch locker.(type) {
	case *sync.Mutex, *sync.RWMutex:
		return
	}

	locker.Lock()
	w.locks[w.depth] = locker
}
예제 #28
0
func interfaceFrom(field reflect.Value, fn func(interface{}, *bool)) {
	// it may be impossible for a struct field to fail this check
	if !field.CanInterface() {
		return
	}
	var ok bool
	fn(field.Interface(), &ok)
	if !ok && field.CanAddr() {
		fn(field.Addr().Interface(), &ok)
	}
}
예제 #29
0
// if this value is a Locker, lock it and add it to the locks slice
func (w *walker) lock(v reflect.Value) {
	if !w.useLocks {
		return
	}

	if !v.IsValid() || !v.CanInterface() {
		return
	}

	type rlocker interface {
		RLocker() sync.Locker
	}

	var locker sync.Locker

	// first check if we can get a locker from the value
	switch l := v.Interface().(type) {
	case rlocker:
		// don't lock a mutex directly
		if _, ok := l.(*sync.RWMutex); !ok {
			locker = l.RLocker()
		}
	case sync.Locker:
		locker = l
	}

	// the value itself isn't a locker, so check the method on a pointer too
	if locker == nil && v.CanAddr() {
		switch l := v.Addr().Interface().(type) {
		case rlocker:
			// don't lock a mutex directly
			if _, ok := l.(*sync.RWMutex); !ok {
				locker = l.RLocker()
			}
		case sync.Locker:
			locker = l
		}
	}

	// still no callable locker
	if locker == nil {
		return
	}

	// don't lock a mutex directly
	switch locker.(type) {
	case *sync.Mutex, *sync.RWMutex:
		return
	}

	locker.Lock()
	w.locks[w.depth] = locker
}
예제 #30
0
파일: encode.go 프로젝트: bartekn/go-xdr
// encodeInterface examines the interface represented by the passed reflection
// value to detect whether it is an interface that can be encoded if it is,
// extracts the underlying value to pass back into the encode function for
// encoding according to its type.
//
// A MarshalError is returned if any issues are encountered while encoding
// the interface.
func (enc *Encoder) encodeInterface(v reflect.Value) (err error) {
	if v.IsNil() || !v.CanInterface() {
		msg := fmt.Sprintf("can't encode nil interface")
		err = marshalError("encodeInterface", ErrNilInterface, msg, nil)
		return err
	}

	// Extract underlying value from the interface and indirect through pointers.
	ve := reflect.ValueOf(v.Interface())
	ve = enc.indirect(ve)
	return enc.encode(ve)
}