예제 #1
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))
}
예제 #2
0
파일: flat.go 프로젝트: hanjin8307/circuit
func unflattenValue(v reflect.Value, t reflect.Type) reflect.Value {
	// When t is an Interface, we can't do much, since we don't know the
	// original (unflattened) type of the value placed in v, so we just nop it.
	if t.Kind() == reflect.Interface {
		return v
	}
	// v can be invalid, if it holds the nil value for pointer type
	if !v.IsValid() {
		return v
	}
	// Make sure v is indeed flat
	if v.Kind() == reflect.Ptr {
		panic("unflattening non-flat value")
	}
	// Add a *, one at a time
	for t.Kind() == reflect.Ptr {
		if v.CanAddr() {
			v = v.Addr()
		} else {
			pw := reflect.New(v.Type())
			pw.Elem().Set(v)
			v = pw
		}
		t = t.Elem()
	}
	return v
}
예제 #3
0
파일: decode.go 프로젝트: MG-RAST/Shock
func (f *decFnInfo) kSlice(rv reflect.Value) {
	// A slice can be set from a map or array in stream.
	currEncodedType := f.dd.currentEncodedType()

	switch currEncodedType {
	case valueTypeBytes, valueTypeString:
		if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
			if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
				rv.SetBytes(bs2)
			}
			return
		}
	}

	if shortCircuitReflectToFastPath && rv.CanAddr() {
		switch f.ti.rtid {
		case intfSliceTypId:
			f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}), currEncodedType, f.array)
			return
		case uint64SliceTypId:
			f.d.decSliceUint64(rv.Addr().Interface().(*[]uint64), currEncodedType, f.array)
			return
		case int64SliceTypId:
			f.d.decSliceInt64(rv.Addr().Interface().(*[]int64), currEncodedType, f.array)
			return
		case strSliceTypId:
			f.d.decSliceStr(rv.Addr().Interface().(*[]string), currEncodedType, f.array)
			return
		}
	}

	containerLen, containerLenS := decContLens(f.dd, currEncodedType)

	// an array can never return a nil slice. so no need to check f.array here.

	if rv.IsNil() {
		rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
	}

	if containerLen == 0 {
		return
	}

	if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
		if f.array { // !rv.CanSet()
			decErr(msgDecCannotExpandArr, rvcap, containerLenS)
		}
		rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
		if rvlen > 0 {
			reflect.Copy(rvn, rv)
		}
		rv.Set(rvn)
	} else if containerLenS > rvlen {
		rv.SetLen(containerLenS)
	}

	for j := 0; j < containerLenS; j++ {
		f.d.decodeValue(rv.Index(j))
	}
}
예제 #4
0
func (scope *Scope) callMethod(methodName string, reflectValue reflect.Value) {
	// Only get address from non-pointer
	if reflectValue.CanAddr() && reflectValue.Kind() != reflect.Ptr {
		reflectValue = reflectValue.Addr()
	}

	if methodValue := reflectValue.MethodByName(methodName); methodValue.IsValid() {
		switch method := methodValue.Interface().(type) {
		case func():
			method()
		case func(*Scope):
			method(scope)
		case func(*DB):
			newDB := scope.NewDB()
			method(newDB)
			scope.Err(newDB.Error)
		case func() error:
			scope.Err(method())
		case func(*Scope) error:
			scope.Err(method(scope))
		case func(*DB) error:
			newDB := scope.NewDB()
			scope.Err(method(newDB))
			scope.Err(newDB.Error)
		default:
			scope.Err(fmt.Errorf("unsupported function %v", methodName))
		}
	}
}
예제 #5
0
파일: command.go 프로젝트: otm/limes
func parseFlagField(field reflect.StructField, fieldVal reflect.Value) *Option {
	checkTags(field, flagTag)
	checkExported(field, flagTag)

	names := parseCommaNames(field.Tag.Get(flagTag))
	if len(names) == 0 {
		panicCommand("at least one flag name must be specified (field %s)", field.Name)
	}

	opt := &Option{
		Names:       names,
		Flag:        true,
		Description: field.Tag.Get(descriptionTag),
	}

	if field.Type.Implements(decoderT) {
		opt.Decoder = fieldVal.Interface().(OptionDecoder)
	} else if fieldVal.CanAddr() && reflect.PtrTo(field.Type).Implements(decoderT) {
		opt.Decoder = fieldVal.Addr().Interface().(OptionDecoder)
	} else {
		switch field.Type.Kind() {
		case reflect.Bool:
			opt.Decoder = NewFlagDecoder(fieldVal.Addr().Interface().(*bool))
		case reflect.Int:
			opt.Decoder = NewFlagAccumulator(fieldVal.Addr().Interface().(*int))
			opt.Plural = true
		default:
			panicCommand("field type not valid as a flag -- did you mean to use %q instead? (field %s)", "option", field.Name)
		}
	}

	opt.validate()
	return opt
}
예제 #6
0
파일: encode.go 프로젝트: eswdd/bosun
func (f encFnInfo) ext(rv reflect.Value) {
	// if this is a struct|array and it was addressable, then pass the address directly (not the value)
	if k := rv.Kind(); (k == reflect.Struct || k == reflect.Array) && rv.CanAddr() {
		rv = rv.Addr()
	}
	f.ee.EncodeExt(rv.Interface(), f.xfTag, f.xfFn, f.e)
}
예제 #7
0
func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) {
	switch val.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(val.Int(), 10), nil, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return strconv.FormatUint(val.Uint(), 10), nil, nil
	case reflect.Float32, reflect.Float64:
		return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil
	case reflect.String:
		return val.String(), nil, nil
	case reflect.Bool:
		return strconv.FormatBool(val.Bool()), nil, nil
	case reflect.Array:
		if typ.Elem().Kind() != reflect.Uint8 {
			break
		}
		// [...]byte
		var bytes []byte
		if val.CanAddr() {
			bytes = val.Slice(0, val.Len()).Bytes()
		} else {
			bytes = make([]byte, val.Len())
			reflect.Copy(reflect.ValueOf(bytes), val)
		}
		return "", bytes, nil
	case reflect.Slice:
		if typ.Elem().Kind() != reflect.Uint8 {
			break
		}
		// []byte
		return "", val.Bytes(), nil
	}
	return "", nil, &UnsupportedTypeError{typ}
}
예제 #8
0
파일: exec.go 프로젝트: jmcadden/EbbRT-gcc
// validateType guarantees that the value is valid and assignable to the type.
func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
	if !value.IsValid() {
		switch typ.Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
			// An untyped nil interface{}. Accept as a proper nil value.
			// TODO: Can we delete the other types in this list? Should we?
			value = reflect.Zero(typ)
		default:
			s.errorf("invalid value; expected %s", typ)
		}
	}
	if !value.Type().AssignableTo(typ) {
		// Does one dereference or indirection work? We could do more, as we
		// do with method receivers, but that gets messy and method receivers
		// are much more constrained, so it makes more sense there than here.
		// Besides, one is almost always all you need.
		switch {
		case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
			value = value.Elem()
		case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
			value = value.Addr()
		default:
			s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
		}
	}
	return value
}
예제 #9
0
func (ce *condAddrEncoder) encode(v reflect.Value) interface{} {
	if v.CanAddr() {
		return ce.canAddrEnc(v)
	} else {
		return ce.elseEnc(v)
	}
}
예제 #10
0
// callCustom calls 'custom' with sv & dv. custom must be a conversion function.
func (c *Converter) callCustom(sv, dv, custom reflect.Value, scope *scope) error {
	if !sv.CanAddr() {
		sv2 := reflect.New(sv.Type())
		sv2.Elem().Set(sv)
		sv = sv2
	} else {
		sv = sv.Addr()
	}
	if !dv.CanAddr() {
		if !dv.CanSet() {
			return scope.errorf("can't addr or set dest.")
		}
		dvOrig := dv
		dv := reflect.New(dvOrig.Type())
		defer func() { dvOrig.Set(dv) }()
	} else {
		dv = dv.Addr()
	}
	args := []reflect.Value{sv, dv, reflect.ValueOf(scope)}
	ret := custom.Call(args)[0].Interface()
	// This convolution is necessary because nil interfaces won't convert
	// to errors.
	if ret == nil {
		return nil
	}
	return ret.(error)
}
예제 #11
0
// encodeFixedArray writes the XDR encoded representation of each element
// in the passed array represented by the reflection value to the encapsulated
// writer and returns the number of bytes written.  The ignoreOpaque flag
// controls whether or not uint8 (byte) elements should be encoded individually
// or as a fixed sequence of opaque data.
//
// A MarshalError is returned if any issues are encountered while encoding
// the array elements.
//
// Reference:
// 	RFC Section 4.12 - Fixed-Length Array
// 	Individually XDR encoded array elements
func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
	// Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
		// Create a slice of the underlying array for better efficiency
		// when possible.  Can't create a slice of an unaddressable
		// value.
		if v.CanAddr() {
			return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
		}

		// When the underlying array isn't addressable fall back to
		// copying the array into a new slice.  This is rather ugly, but
		// the inability to create a constant slice from an
		// unaddressable array is a limitation of Go.
		slice := make([]byte, v.Len(), v.Len())
		reflect.Copy(reflect.ValueOf(slice), v)
		return enc.EncodeFixedOpaque(slice)
	}

	// Encode each array element.
	var n int
	for i := 0; i < v.Len(); i++ {
		n2, err := enc.encode(v.Index(i))
		n += n2
		if err != nil {
			return n, err
		}
	}

	return n, nil
}
예제 #12
0
파일: encode.go 프로젝트: carriercomm/os
func (e *Encoder) emitAddrMarshaler(tag string, v reflect.Value) {
	if !v.CanAddr() {
		e.marshal(tag, v, false)
		return
	}

	va := v.Addr()
	if va.IsNil() {
		e.emitNil()
		return
	}

	m := v.Interface().(Marshaler)
	t, val, err := m.MarshalYAML()
	if err != nil {
		panic(err)
	}

	if val == nil {
		e.emitNil()
		return
	}

	e.marshal(t, reflect.ValueOf(val), false)
}
예제 #13
0
func (d *decodeState) indirect(v reflect.Value, decodingNull bool) reflect.Value {
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}
예제 #14
0
func (c *completion) completeValue(value reflect.Value, prefix string, match string, isRemaining bool) []Completion {
	// For remaining positional args (that are parsed into a slice), complete
	// based on the element type.
	if isRemaining {
		value = reflect.New(value.Type().Elem())
	}

	i := value.Interface()

	var ret []Completion

	if cmp, ok := i.(Completer); ok {
		ret = cmp.Complete(match)
	} else if value.CanAddr() {
		if cmp, ok = value.Addr().Interface().(Completer); ok {
			ret = cmp.Complete(match)
		}
	}

	for i, v := range ret {
		ret[i].Item = prefix + v.Item
	}

	return ret
}
예제 #15
0
파일: exec.go 프로젝트: bibbyflyaway/go
// validateType guarantees that the value is valid and assignable to the type.
func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
	if !value.IsValid() {
		if typ == nil || canBeNil(typ) {
			// An untyped nil interface{}. Accept as a proper nil value.
			return reflect.Zero(typ)
		}
		s.errorf("invalid value; expected %s", typ)
	}
	if typ != nil && !value.Type().AssignableTo(typ) {
		if value.Kind() == reflect.Interface && !value.IsNil() {
			value = value.Elem()
			if value.Type().AssignableTo(typ) {
				return value
			}
			// fallthrough
		}
		// Does one dereference or indirection work? We could do more, as we
		// do with method receivers, but that gets messy and method receivers
		// are much more constrained, so it makes more sense there than here.
		// Besides, one is almost always all you need.
		switch {
		case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
			value = value.Elem()
			if !value.IsValid() {
				s.errorf("dereference of nil pointer of type %s", typ)
			}
		case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
			value = value.Addr()
		default:
			s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
		}
	}
	return value
}
예제 #16
0
파일: decode.go 프로젝트: kezhuw/toml
func indirectValue(v reflect.Value) (encoding.TextUnmarshaler, reflect.Value) {
	if v.Kind() != reflect.Ptr && v.CanAddr() {
		v = v.Addr()
	}
	var u encoding.TextUnmarshaler
	for {
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() {
				v = e
				continue
			}
		}
		if v.Kind() != reflect.Ptr {
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.NumMethod() > 0 {
			// TOML has native Datetime support, while time.Time implements
			// encoding.TextUnmarshaler. For native Datetime, we need settable
			// time.Time struct, so continue here.
			if i, ok := v.Interface().(encoding.TextUnmarshaler); ok {
				u = i
			}
		}
		v = v.Elem()
	}
	return u, v
}
예제 #17
0
파일: dec_helpers.go 프로젝트: pjump/gcc
func decComplex128Array(state *decoderState, v reflect.Value, length int, ovfl error) bool {
	// Can only slice if it is addressable.
	if !v.CanAddr() {
		return false
	}
	return decComplex128Slice(state, v.Slice(0, v.Len()), length, ovfl)
}
예제 #18
0
파일: encode.go 프로젝트: 2thetop/go
func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	if v.CanAddr() {
		ce.canAddrEnc(e, v, opts)
	} else {
		ce.elseEnc(e, v, opts)
	}
}
예제 #19
0
파일: encode.go 프로젝트: eswdd/bosun
func (f encFnInfo) getValueForMarshalInterface(rv reflect.Value, indir int8) (v interface{}, proceed bool) {
	if indir == 0 {
		v = rv.Interface()
	} else if indir == -1 {
		// If a non-pointer was passed to Encode(), then that value is not addressable.
		// Take addr if addresable, else copy value to an addressable value.
		if rv.CanAddr() {
			v = rv.Addr().Interface()
		} else {
			rv2 := reflect.New(rv.Type())
			rv2.Elem().Set(rv)
			v = rv2.Interface()
			// fmt.Printf("rv.Type: %v, rv2.Type: %v, v: %v\n", rv.Type(), rv2.Type(), v)
		}
	} else {
		for j := int8(0); j < indir; j++ {
			if rv.IsNil() {
				f.ee.EncodeNil()
				return
			}
			rv = rv.Elem()
		}
		v = rv.Interface()
	}
	return v, true
}
예제 #20
0
// indirect will walk a value's interface or pointer value types. Returning
// the final value or the value a unmarshaler is defined on.
//
// Based on the enoding/json type reflect value type indirection in Go Stdlib
// https://golang.org/src/encoding/json/decode.go indirect func.
func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
				v = e
				continue
			}
		}
		if v.Kind() != reflect.Ptr {
			break
		}
		if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.Type().NumMethod() > 0 {
			if u, ok := v.Interface().(Unmarshaler); ok {
				return u, reflect.Value{}
			}
		}
		v = v.Elem()
	}

	return nil, v
}
예제 #21
0
파일: decode.go 프로젝트: nsf/libtorgo
func (d *decoder) parse_unmarshaler(v reflect.Value) bool {
	m, ok := v.Interface().(Unmarshaler)
	if !ok {
		// T doesn't work, try *T
		if v.Kind() != reflect.Ptr && v.CanAddr() {
			m, ok = v.Addr().Interface().(Unmarshaler)
			if ok {
				v = v.Addr()
			}
		}
	}
	if ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
		if d.read_one_value() {
			err := m.UnmarshalBencode(d.buf.Bytes())
			d.buf.Reset()
			if err != nil {
				panic(&UnmarshalerError{v.Type(), err})
			}
			return true
		}
		d.buf.Reset()
	}

	return false
}
예제 #22
0
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
func indirect(v reflect.Value) reflect.Value {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}
예제 #23
0
파일: encoder.go 프로젝트: erkl/binn
func encodeByteArray(b []byte, v reflect.Value) []byte {
	n := v.Len()

	if n < (0xec - 0xe0) {
		b = append(b, byte(0xe0+n))
	} else {
		b = encodeK4(b, 0xec, uint64(n))
	}

	// Fast path for when the array is addressable (which it almost
	// always will be).
	if v.CanAddr() {
		return append(b, v.Slice(0, n).Bytes()...)
	}

	i := len(b)
	j := i + n

	if j > cap(b) {
		t := make([]byte, i, j)
		copy(t, b)
		b = t
	}

	reflect.Copy(reflect.ValueOf(b[i:j]), v)
	return b[:j]
}
예제 #24
0
파일: util_db.go 프로젝트: fishedee/fishgo
func (this *databaseImplement) autoMapType(v reflect.Value) *core.Table {
	t := v.Type()
	table := core.NewEmptyTable()
	if tb, ok := v.Interface().(tableName); ok {
		table.Name = tb.TableName()
	} else {
		if v.CanAddr() {
			if tb, ok = v.Addr().Interface().(tableName); ok {
				table.Name = tb.TableName()
			}
		}
		if table.Name == "" {
			table.Name = this.TableMapper.Obj2Table(t.Name())
		}
	}
	table.Type = t
	for i := 0; i < t.NumField(); i++ {
		tag := t.Field(i).Tag
		ormTagStr := tag.Get("xorm")
		if ormTagStr == "-" || ormTagStr == "<-" {
			continue
		}
		col := &core.Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
			IsAutoIncrement: false, MapType: core.TWOSIDES, Indexes: make(map[string]bool)}
		col.Name = this.ColumnMapper.Obj2Table(t.Field(i).Name)
		table.AddColumn(col)
	}
	return table
}
예제 #25
0
파일: encode.go 프로젝트: ossrs/go-oryx-lib
func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
	if v.CanAddr() {
		ce.canAddrEnc(e, v, quoted)
	} else {
		ce.elseEnc(e, v, quoted)
	}
}
예제 #26
0
func EncodeStructContent(buf *bytes2.ChunkedWriter, val reflect.Value) {
	// check the Marshaler interface on T
	if marshaler, ok := val.Interface().(Marshaler); ok {
		marshaler.MarshalBson(buf)
		return
	}
	// check the Marshaler interface on *T
	if val.CanAddr() {
		if marshaler, ok := val.Addr().Interface().(Marshaler); ok {
			marshaler.MarshalBson(buf)
			return
		}
	}

	lenWriter := NewLenWriter(buf)
	t := val.Type()
	for i := 0; i < t.NumField(); i++ {
		key := t.Field(i).Name

		// NOTE(szopa): Ignore private fields (copied from
		// encoding/json). Yes, it feels like a hack.
		if t.Field(i).PkgPath != "" {
			continue
		}
		encodeField(buf, key, val.Field(i))
	}
	buf.WriteByte(0)
	lenWriter.RecordLen()
}
예제 #27
0
파일: path_value.go 프로젝트: kuenzaa/rack
func setValue(dstVal reflect.Value, src interface{}) {
	if dstVal.Kind() == reflect.Ptr {
		dstVal = reflect.Indirect(dstVal)
	}
	srcVal := reflect.ValueOf(src)

	if !srcVal.IsValid() { // src is literal nil
		if dstVal.CanAddr() {
			// Convert to pointer so that pointer's value can be nil'ed
			//                     dstVal = dstVal.Addr()
		}
		dstVal.Set(reflect.Zero(dstVal.Type()))

	} else if srcVal.Kind() == reflect.Ptr {
		if srcVal.IsNil() {
			srcVal = reflect.Zero(dstVal.Type())
		} else {
			srcVal = reflect.ValueOf(src).Elem()
		}
		dstVal.Set(srcVal)
	} else {
		dstVal.Set(srcVal)
	}

}
예제 #28
0
func getSetter(outt reflect.Type, out reflect.Value) Setter {
	setterMutex.RLock()
	style := setterStyle[outt]
	setterMutex.RUnlock()
	if style == setterNone {
		return nil
	}
	if style == setterUnknown {
		setterMutex.Lock()
		defer setterMutex.Unlock()
		if outt.Implements(setterIface) {
			setterStyle[outt] = setterType
		} else if reflect.PtrTo(outt).Implements(setterIface) {
			setterStyle[outt] = setterAddr
		} else {
			setterStyle[outt] = setterNone
			return nil
		}
		style = setterStyle[outt]
	}
	if style == setterAddr {
		if !out.CanAddr() {
			return nil
		}
		out = out.Addr()
	} else if outt.Kind() == reflect.Ptr && out.IsNil() {
		out.Set(reflect.New(outt.Elem()))
	}
	return out.Interface().(Setter)
}
예제 #29
0
func getCurrentContainer(current reflect.Value) *Container {
	if !current.CanAddr() {
		return nil
	}
	currentContainer, _ := current.Addr().Interface().(*Container)
	return currentContainer
}
예제 #30
0
func indirect(v reflect.Value) reflect.Value {
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}