Beispiel #1
1
func (par field) WriteValue(out io.Writer, valueOf reflect.Value) error {
	if (par.Flags & (fieldNotAny | fieldFollowedBy)) != 0 {
		return nil
	}

	if par.Index < 0 { // We can not out this value in all cases but if it was literal we can do it
		// TODO: Check if it is string and output only in case it is literal
		p := par.Parse
		v := valueOf
		for {
			switch tp := p.(type) {
			case *ptrParser:
				p = tp.Parser
				if v.IsNil() {
					if tp.Optional {
						return nil
					}
					return errors.New("Ptr value is nil")
				}
				v = v.Elem()
				break

			case *literalParser:
				_, err := out.Write([]byte(tp.Literal))
				return err
			default:
				return errors.New("Could not out anonymous field if it is not literal")
			}
		}
	} else {
		f := valueOf.Field(par.Index)
		return par.Parse.WriteValue(out, f)
	}
}
Beispiel #2
0
func (e *Encoder) encodeStruct(rv reflect.Value, name string, inlist bool) error {
	err := e.emit(tagCompound, name, inlist)
	if err != nil {
		return err
	}

	rt := rv.Type()

	for i := 0; i < rv.NumField(); i++ {
		fv := rv.Field(i)
		ft := rt.Field(i)

		if hasField(ft.Tag.Get("nbt"), "omitempty") && isEmpty(fv) {
			continue
		}

		fname := tagField(ft.Tag.Get("nbt"), 0)
		if len(fname) == 0 {
			fname = ft.Name
		}

		// Special-case time.Time
		if e.isTime(ft.Type) {
			t := fv.Interface().(time.Time).Unix()
			fv = reflect.ValueOf(t)
		}

		err = e.encode(fv, fname, false)
		if err != nil {
			return err
		}
	}

	return e.writeU8(uint8(tagEnd))
}
Beispiel #3
0
func isZero(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Func, reflect.Map, reflect.Slice:
		return v.IsNil()
	case reflect.Array:
		z := true
		for i := 0; i < v.Len(); i++ {
			z = z && isZero(v.Index(i))
		}
		return z
	case reflect.Struct:
		if v.Type() == reflect.TypeOf(t) {
			if v.Interface().(time.Time).IsZero() {
				return true
			}
			return false
		}
		z := true
		for i := 0; i < v.NumField(); i++ {
			z = z && isZero(v.Field(i))
		}
		return z
	}
	// Compare other types directly:
	z := reflect.Zero(v.Type())
	return v.Interface() == z.Interface()
}
Beispiel #4
0
func readStruct(in io.Reader, obj reflect.Value) {
	for i := 0; i < obj.Type().NumField(); i++ {
		if obj.Type().Field(i).PkgPath == "" {
			readAny(in, obj.Field(i))
		}
	}
}
Beispiel #5
0
func (e *encoder) addStruct(v reflect.Value) {
	sinfo, err := getStructInfo(v.Type())
	if err != nil {
		panic(err)
	}
	var value reflect.Value
	if sinfo.InlineMap >= 0 {
		m := v.Field(sinfo.InlineMap)
		if m.Len() > 0 {
			for _, k := range m.MapKeys() {
				ks := k.String()
				if _, found := sinfo.FieldsMap[ks]; found {
					panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", ks))
				}
				e.addElem(ks, m.MapIndex(k), false)
			}
		}
	}
	for _, info := range sinfo.FieldsList {
		if info.Inline == nil {
			value = v.Field(info.Num)
		} else {
			value = v.FieldByIndex(info.Inline)
		}
		if info.OmitEmpty && isZero(value) {
			continue
		}
		e.addElem(info.Key, value, info.MinSize)
	}
}
Beispiel #6
0
func addFields(m *Model, t reflect.Type, v reflect.Value) {
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		sqlTag := field.Tag.Get("sql")
		if sqlTag == "-" {
			continue
		}
		if field.Anonymous && field.Type.Kind() == reflect.Struct {
			addFields(m, field.Type, v.Field(i))
			continue
		}
		parsedSqlTags := parseTags(sqlTag)
		rawValidateTag := field.Tag.Get("validate")
		parsedValidateTags := make(map[string]string)
		if len(rawValidateTag) > 0 {
			if rawValidateTag[:1] == "^" {
				parsedValidateTags["regexp"] = rawValidateTag
			} else {
				parsedValidateTags = parseTags(rawValidateTag)
			}
		}
		fd := &ModelField{
			Name:         toSnake(field.Name),
			Value:        v.FieldByName(field.Name).Interface(),
			SqlTags:      parsedSqlTags,
			ValidateTags: parsedValidateTags,
			RawTag:       field.Tag,
		}
		if fd.PrimaryKey() {
			m.Pk = fd
		}
		m.Fields = append(m.Fields, fd)
	}
}
Beispiel #7
0
func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) {
	t := value.Type()
	var inlineValue *reflect.Value
	for ix := 0; ix < t.NumField(); ix++ {
		f := t.Field(ix)
		jsonTag := f.Tag.Get("json")
		parts := strings.Split(jsonTag, ",")
		if len(parts) == 0 {
			continue
		}
		if parts[0] == node.Value {
			return value.Field(ix), nil
		}
		if len(parts[0]) == 0 {
			val := value.Field(ix)
			inlineValue = &val
		}
	}
	if inlineValue != nil {
		if inlineValue.Kind() == reflect.Struct {
			// handle 'inline'
			match, err := j.findFieldInValue(inlineValue, node)
			if err != nil {
				return reflect.Value{}, err
			}
			if match.IsValid() {
				return match, nil
			}
		}
	}
	return value.FieldByName(node.Value), nil
}
Beispiel #8
0
func marshal(buf []byte, prefix string, rv reflect.Value, inArray, arrayTable bool) ([]byte, error) {
	rt := rv.Type()
	for i := 0; i < rv.NumField(); i++ {
		ft := rt.Field(i)
		if !ast.IsExported(ft.Name) {
			continue
		}
		colName, rest := extractTag(rt.Field(i).Tag.Get(fieldTagName))
		if colName == tagSkip {
			continue
		}
		if colName == "" {
			colName = stringutil.ToSnakeCase(ft.Name)
		}
		fv := rv.Field(i)
		switch rest {
		case tagOmitempty:
			if fv.Interface() == reflect.Zero(ft.Type).Interface() {
				continue
			}
		}
		var err error
		if buf, err = encodeValue(buf, prefix, colName, fv, inArray, arrayTable); err != nil {
			return nil, err
		}
	}
	return buf, nil
}
Beispiel #9
0
// visit calls the visitor function for each string it finds, and will descend
// recursively into structures and slices. If any visitor returns an error then
// the search will stop and that error will be returned.
func visit(path string, v reflect.Value, t reflect.Type, fn visitor) error {
	switch v.Kind() {
	case reflect.String:
		return fn(path, v)
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			vf := v.Field(i)
			tf := t.Field(i)
			newPath := fmt.Sprintf("%s.%s", path, tf.Name)
			if err := visit(newPath, vf, tf.Type, fn); err != nil {
				return err
			}
		}
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			vi := v.Index(i)
			ti := vi.Type()
			newPath := fmt.Sprintf("%s[%d]", path, i)
			if err := visit(newPath, vi, ti, fn); err != nil {
				return err
			}
		}
	}
	return nil
}
Beispiel #10
0
// 向tree.nodes中添加元素。
// originV v的原始值,比如originV可能是指针,而v绝对不会是指针。
func (t *tree) addNode(field reflect.StructField, v, originV reflect.Value) error {
	name := tag.MustGet(field.Tag.Get("ini"), "name", field.Name)[0]

	t.nodes[name] = make(map[string]*elem)
	typ := v.Type()
	for i := 0; i < typ.NumField(); i++ {
		f := v.Field(i)
		if f.Kind() == reflect.Ptr {
			f = f.Elem()
		}

		if f.Kind() == reflect.Ptr {
			return fmt.Errorf("[%v]的值为指针的指针", name)
		}
		if f.Kind() == reflect.Struct {
			return errors.New("不支持多层嵌套")
		}

		if err := addElem(t.nodes[name], typ.Field(i), v.Field(i), originV); err != nil {
			return err
		}
	}

	return nil
}
Beispiel #11
0
func (state *marshalState) marshalStruct(v reflect.Value) error {
	state.writeString("<< ")
	t := v.Type()
	n := v.NumField()
	for i := 0; i < n; i++ {
		f := t.Field(i)
		if f.PkgPath != "" {
			continue
		}

		tag, omitEmpty := f.Name, false
		if tv := f.Tag.Get("pdf"); tv != "" {
			if tv == "-" {
				continue
			}

			name, options := parseTag(tv)
			if name != "" {
				tag = name
			}
			omitEmpty = options.Contains("omitempty")
		}

		fieldValue := v.Field(i)
		if omitEmpty && isEmptyValue(fieldValue) {
			continue
		}

		state.marshalKeyValue(name(tag), fieldValue)
	}
	state.writeString(">>")
	return nil
}
Beispiel #12
0
func getTemplateFields(keys []string, s reflect.Value) []TemplateField {
	var fields []TemplateField

	typeOfSpec := s.Type()
	for i := 0; i < s.NumField(); i++ {
		f := s.Field(i)
		t := typeOfSpec.Field(i)
		if f.CanSet() {
			fieldName := typeOfSpec.Field(i).Name

			if f.Kind() == reflect.Struct {
				keys = append(keys, fieldName)
				fields = append(fields, getTemplateFields(keys, f)...)
				continue
			}

			fields = append(fields, TemplateField{
				Name:   fieldName,
				Value:  f.Interface(),
				String: fmt.Sprintf("%#v", f.Interface()),
				Type:   t.Type,
				Tags:   getTags(t.Tag),
			})
		}
	}

	return fields
}
Beispiel #13
0
func structValue(m map[string]reflect.Value, value reflect.Value) {
	if value.Type().Implements(typeValuer) {
		return
	}
	switch value.Kind() {
	case reflect.Ptr:
		if value.IsNil() {
			return
		}
		structValue(m, value.Elem())
	case reflect.Struct:
		t := value.Type()
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if field.PkgPath != "" && !field.Anonymous {
				// unexported
				continue
			}
			tag := field.Tag.Get("db")
			if tag == "-" {
				// ignore
				continue
			}
			if tag == "" {
				// no tag, but we can record the field name
				tag = camelCaseToSnakeCase(field.Name)
			}
			fieldValue := value.Field(i)
			if _, ok := m[tag]; !ok {
				m[tag] = fieldValue
			}
			structValue(m, fieldValue)
		}
	}
}
Beispiel #14
0
func (c *Client) setStruct(directory string, value *reflect.Value) (err error) {
	tv := value.Type()
	for i := 0; i < value.NumField(); i++ {
		if tagv := tv.Field(i).Tag.Get(c.tag); tagv != "" {
			field := value.Field(i)
			if field.Kind() == reflect.Struct {
				if err := c.setStruct(path.Join(directory, tagv), &field); err != nil {
					return err
				}
			} else {
				key := path.Join(directory, tagv)
				response, err := c.client.Get(key, false, false)
				if err != nil {
					return err
				}

				value := response.Node.Value
				switch field.Kind() {
				case reflect.String:
					field.SetString(value)
				case reflect.Int64:
					i, _ := strconv.Atoi(value)
					field.SetInt(int64(i))
				case reflect.Int:
					i, _ := strconv.Atoi(value)
					field.SetInt(int64(i))
				}
			}
		}
	}
	return nil
}
Beispiel #15
0
// appendStruct is an internal helper function to AppendConfig. Given two values
// of structures (assumed to be the same type), recursively iterate over every
// field in the struct, appending slices, recursively appending structs, and
// overwriting old values with the new for all other types. Individual fields
// are able to override their merge strategy using the "merge" tag. Accepted
// values are "new" or "old": "new" uses the new value, "old" uses the old
// value. These are currently only used for "ignition.config" and
// "ignition.version".
func appendStruct(vOld, vNew reflect.Value) reflect.Value {
	tOld := vOld.Type()
	vRes := reflect.New(tOld)

	for i := 0; i < tOld.NumField(); i++ {
		vfOld := vOld.Field(i)
		vfNew := vNew.Field(i)
		vfRes := vRes.Elem().Field(i)

		switch tOld.Field(i).Tag.Get("merge") {
		case "old":
			vfRes.Set(vfOld)
			continue
		case "new":
			vfRes.Set(vfNew)
			continue
		}

		switch vfOld.Type().Kind() {
		case reflect.Struct:
			vfRes.Set(appendStruct(vfOld, vfNew))
		case reflect.Slice:
			vfRes.Set(reflect.AppendSlice(vfOld, vfNew))
		default:
			vfRes.Set(vfNew)
		}
	}

	return vRes.Elem()
}
Beispiel #16
0
func (m *source) initializeItem(val reflect.Value) error {
	for val.Type().Kind() == reflect.Ptr {
		val = val.Elem()
	}

	vfn := fullNameFor(val.Type())
	if vfn != m.FullName {
		return fmt.Errorf("Slice Mapper for %s cannot initialize %s", m.FullName, vfn)
	}

	if val.Type().Kind() != reflect.Struct {
		return fmt.Errorf("Could not map data of kind %s", val.Kind().String())
	}

	if !m.hasMixin {
		return fmt.Errorf("Struct %s does not have a mixin to initialize", m.Name)
	}

	mx := new(Mixin)
	mx.model = m
	mx.instance = val
	val.Field(m.mixinField).Set(reflect.ValueOf(mx))

	return nil
}
Beispiel #17
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()
}
Beispiel #18
0
// isZero reports whether the value is the zero of its type.
func isZero(val reflect.Value) bool {
	switch val.Kind() {
	case reflect.Array:
		for i := 0; i < val.Len(); i++ {
			if !isZero(val.Index(i)) {
				return false
			}
		}
		return true
	case reflect.Map, reflect.Slice, reflect.String:
		return val.Len() == 0
	case reflect.Bool:
		return !val.Bool()
	case reflect.Complex64, reflect.Complex128:
		return val.Complex() == 0
	case reflect.Chan, reflect.Func, reflect.Ptr:
		return val.IsNil()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return val.Int() == 0
	case reflect.Float32, reflect.Float64:
		return val.Float() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return val.Uint() == 0
	case reflect.Struct:
		for i := 0; i < val.NumField(); i++ {
			if !isZero(val.Field(i)) {
				return false
			}
		}
		return true
	}
	panic("unknown type in isZero " + val.Type().String())
}
Beispiel #19
0
func getSqlFieldsFromJson(updateData map[string]interface{}, v reflect.Value, sqlData map[string]interface{}) error {
	for i := 0; i < v.NumField(); i++ {
		if v.Type().Field(i).Type.Kind() == reflect.Struct {
			subUpdateData := updateData
			if tag := v.Type().Field(i).Tag.Get("json"); tag != "" {
				maybeSubUpdateData := updateData[tag]
				if yesSubUpdateData, ok := maybeSubUpdateData.(map[string]interface{}); ok {
					subUpdateData = yesSubUpdateData
				}
			}
			getSqlFieldsFromJson(subUpdateData, v.Field(i), sqlData)
			continue
		}

		fieldName := v.Type().Field(i).Name
		columnName := sqlCase(fieldName)
		if tag := v.Type().Field(i).Tag.Get("sql"); tag != "" {
			columnName = tag
		}
		jsonName := fieldName
		if tag := v.Type().Field(i).Tag.Get("json"); tag != "" {
			jsonName = tag
		}
		if val, ok := updateData[jsonName]; ok {
			sqlData[columnName] = val
		}
	}
	return nil
}
Beispiel #20
0
func (d decoder) decodeField(sf reflect.StructField, t reflect.Type, v reflect.Value) MessageRejectError {
	if sf.Tag.Get("fix") != "" {
		fixTag, err := strconv.Atoi(sf.Tag.Get("fix"))
		if err != nil {
			panic(err)
		}

		if !d.FieldMap.Has(Tag(fixTag)) {
			return nil
		}

		return d.decodeValue(Tag(fixTag), t, v)
	}

	switch t.Kind() {
	case reflect.Ptr:
		v.Set(reflect.New(t.Elem()))
		return d.decodeField(sf, t.Elem(), v.Elem())
	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			if err := d.decodeField(t.Field(i), t.Field(i).Type, v.Field(i)); err != nil {
				return err
			}
		}
	}

	return nil
}
Beispiel #21
0
func writeStruct(out io.Writer, obj reflect.Value) {
	for i := 0; i < obj.Type().NumField(); i++ {
		if obj.Type().Field(i).PkgPath == "" {
			writeAny(out, obj.Field(i))
		}
	}
}
Beispiel #22
0
func mergeStruct(out, in reflect.Value) {
	sprop := GetProperties(in.Type())
	for i := 0; i < in.NumField(); i++ {
		f := in.Type().Field(i)
		if strings.HasPrefix(f.Name, "XXX_") {
			continue
		}
		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
	}

	if emIn, ok := in.Addr().Interface().(extensionsMap); ok {
		emOut := out.Addr().Interface().(extensionsMap)
		mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap())
	} else if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
		emOut := out.Addr().Interface().(extensionsBytes)
		bIn := emIn.GetExtensions()
		bOut := emOut.GetExtensions()
		*bOut = append(*bOut, *bIn...)
	}

	uf := in.FieldByName("XXX_unrecognized")
	if !uf.IsValid() {
		return
	}
	uin := uf.Bytes()
	if len(uin) > 0 {
		out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
	}
}
Beispiel #23
0
func (enc *encoder) writeStruct(val reflect.Value) {
	for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
		val = val.Elem()
	}
	if val.Kind() != reflect.Struct {
		enc.error(&UnsupportedValueError{Value: val, Message: "expect a struct"})
	}
	marker := &MStruct{}
	if err := enc.proto.WriteStructBegin(enc.writer, marker); err != nil {
		enc.error(err)
	}
	for _, ef := range encodeFields(val.Type()).fields {
		field := val.Type().Field(ef.i)
		fieldValue := val.Field(ef.i)

		if isEmptyValue(fieldValue) {
			continue
		}

		mfield := &MField{Name: field.Name, Type: ef.fieldType, ID: ef.id}
		if err := enc.proto.WriteFieldBegin(enc.writer, mfield); err != nil {
			enc.error(err)
		}
		enc.writeValue(fieldValue, ef.fieldType)
	}
	enc.proto.WriteFieldStop(enc.writer)
}
Beispiel #24
0
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
	sinfo, err := getStructInfo(out.Type())
	if err != nil {
		panic(err)
	}
	name := settableValueOf("")
	l := len(n.children)
	for i := 0; i < l; i += 2 {
		ni := n.children[i]
		if isMerge(ni) {
			d.merge(n.children[i+1], out)
			continue
		}
		if !d.unmarshal(ni, name) {
			continue
		}
		if info, ok := sinfo.FieldsMap[name.String()]; ok {
			var field reflect.Value
			if info.Inline == nil {
				field = out.Field(info.Num)
			} else {
				field = out.FieldByIndex(info.Inline)
			}
			d.unmarshal(n.children[i+1], field)
		}
	}
	return true
}
Beispiel #25
0
func visitStruct(val reflect.Value, visitor structVisitor) error {
	if val.Kind() != reflect.Ptr {
		return errNoPointer
	}
	val = reflect.Indirect(val)
	if val.Kind() != reflect.Struct {
		return errNoStruct
	}
	typ := val.Type()
	for ii := 0; ii < typ.NumField(); ii++ {
		field := typ.Field(ii)
		fieldVal := val.Field(ii)
		ptr := fieldVal.Addr().Interface()
		name := defaultFieldName(field.Name)
		var help string
		if n := field.Tag.Get("name"); n != "" {
			name = n
		}
		if h := field.Tag.Get("help"); h != "" {
			help = h
		}
		if name == "" {
			return fmt.Errorf("no name provided for field %s in type %s", field.Name, typ)
		}
		if err := visitor(name, help, &field, fieldVal, ptr); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #26
0
func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) {
	for i := 0; i < st.NumField(); i++ {
		field := sv.Field(i)
		tag, omitempty := jsonTag(st.Field(i))
		if len(tag) == 0 {
			continue
		}
		ft := field.Type()

		kind := ft.Kind()
		if isPointerKind(kind) {
			kind = ft.Elem().Kind()
			if !field.IsNil() {
				field = reflect.Indirect(field)
			}
		}

		switch {
		case isValueKind(kind):
			addParam(result, tag, omitempty, field)
		case kind == reflect.Array || kind == reflect.Slice:
			if isValueKind(ft.Elem().Kind()) {
				addListOfParams(result, tag, omitempty, field)
			}
		case isStructKind(kind) && !(zeroValue(field) && omitempty):
			convertStruct(result, ft, field)
		}
	}
}
Beispiel #27
0
// getField gets the i'th field of the struct value.
// If the field is itself is an interface, return a value for
// the thing inside the interface, not the interface itself.
func getField(v reflect.Value, i int) reflect.Value {
	val := v.Field(i)
	if val.Kind() == reflect.Interface && !val.IsNil() {
		val = val.Elem()
	}
	return val
}
Beispiel #28
0
func display(name string, v reflect.Value) {
	switch v.Kind() { //uint
	case reflect.Invalid:
		fmt.Printf("%s = invalid\n", name)
	case reflect.Slice, reflect.Array:
		for i := 0; i < v.Len(); i++ {
			display(fmt.Sprintf("%s[%d]", name, i), v.Index(i))
		}
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			fieldPath := fmt.Sprintf("%s.%s", name, v.Type().Field(i).Name)
			display(fieldPath, v.Field(i))
		}
	case reflect.Map:
		for _, key := range v.MapKeys() {
			display(fmt.Sprintf("%s[%s]", name,
				formatAtom(key)), v.MapIndex(key))
		}
	case reflect.Ptr:
		if v.IsNil() {
			fmt.Printf("%s = nil\n", name)
		} else {
			display(fmt.Sprintf("(*%s)", name), v.Elem())
		}
	case reflect.Interface:
		if v.IsNil() {
			fmt.Printf("%s = nil\n", name)
		} else {
			fmt.Printf("%s.type = %s\n", name, v.Elem().Type())
			display(name+".value", v.Elem())
		}
	default: // basic types, channels, funcs
		fmt.Printf("%s = %s\n", name, formatAtom(v))
	}
}
Beispiel #29
0
func isZero(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.String:
		return len(v.String()) == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	case reflect.Slice:
		return v.Len() == 0
	case reflect.Map:
		return v.Len() == 0
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Struct:
		vt := v.Type()
		for i := v.NumField() - 1; i >= 0; i-- {
			if vt.Field(i).PkgPath != "" {
				continue // Private field
			}
			if !isZero(v.Field(i)) {
				return false
			}
		}
		return true
	}
	return false
}
Beispiel #30
0
func (c *EC2Client) loadStruct(v url.Values, value reflect.Value, prefix string) error {
	if !value.IsValid() {
		return nil
	}

	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		value := value.Field(i)
		name := t.Field(i).Tag.Get("ec2")

		if name == "" {
			name = t.Field(i).Name
		}
		if prefix != "" {
			name = prefix + "." + name
		}
		switch casted := value.Interface().(type) {
		case StringValue:
			if casted != nil {
				v.Set(name, *casted)
			}
		case BooleanValue:
			if casted != nil {
				v.Set(name, strconv.FormatBool(*casted))
			}
		case LongValue:
			if casted != nil {
				v.Set(name, strconv.FormatInt(*casted, 10))
			}
		case IntegerValue:
			if casted != nil {
				v.Set(name, strconv.Itoa(*casted))
			}
		case DoubleValue:
			if casted != nil {
				v.Set(name, strconv.FormatFloat(*casted, 'f', -1, 64))
			}
		case FloatValue:
			if casted != nil {
				v.Set(name, strconv.FormatFloat(float64(*casted), 'f', -1, 32))
			}
		case []string:
			if len(casted) != 0 {
				for i, val := range casted {
					v.Set(fmt.Sprintf("%s.%d", name, i+1), val)
				}
			}
		case time.Time:
			if !casted.IsZero() {
				const ISO8601UTC = "2006-01-02T15:04:05Z"
				v.Set(name, casted.UTC().Format(ISO8601UTC))
			}
		default:
			if err := c.loadValues(v, value.Interface(), name); err != nil {
				return err
			}
		}
	}
	return nil
}