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) } }
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)) }
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() }
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)) } } }
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) } }
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) } }
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 }
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 }
// 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 }
// 向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 }
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 }
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 }
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) } } }
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 }
// 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() }
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 }
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() }
// 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()) }
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 }
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 }
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)) } } }
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...)) } }
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) }
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 }
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 }
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) } } }
// 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 }
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)) } }
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 }
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 }