// encodeStruct encodes a single struct value. func (enc *Encoder) encodeStruct(b *encBuffer, engine *encEngine, value reflect.Value) { if !valid(value) { return } state := enc.newEncoderState(b) defer enc.freeEncoderState(state) state.fieldnum = -1 for i := 0; i < len(engine.instr); i++ { instr := &engine.instr[i] if i >= value.NumField() { // encStructTerminator instr.op(instr, state, reflect.Value{}) break } field := value.FieldByIndex(instr.index) if instr.indir > 0 { field = encIndirect(field, instr.indir) // TODO: Is field guaranteed valid? If so we could avoid this check. if !valid(field) { continue } } instr.op(instr, state, field) } }
func structToMap(vstruct reflect.Value, schema Schema) (map[string]Value, error) { if vstruct.Kind() == reflect.Ptr { vstruct = vstruct.Elem() } if !vstruct.IsValid() { return nil, nil } m := map[string]Value{} if vstruct.Kind() != reflect.Struct { return nil, fmt.Errorf("bigquery: type is %s, need struct or struct pointer", vstruct.Type()) } fields, err := fieldCache.Fields(vstruct.Type()) if err != nil { return nil, err } for _, schemaField := range schema { // Look for an exported struct field with the same name as the schema // field, ignoring case. structField := fields.Match(schemaField.Name) if structField == nil { continue } val, err := structFieldToUploadValue(vstruct.FieldByIndex(structField.Index), schemaField) if err != nil { return nil, err } // Add the value to the map, unless it is nil. if val != nil { m[schemaField.Name] = val } } return m, nil }
// marshal is the internal version of Marshal. func marshal(p *Params, xv reflect.Value, pt *requestType) error { xv = xv.Elem() for _, f := range pt.fields { fv := xv.FieldByIndex(f.index) if f.isPointer { if fv.IsNil() { continue } fv = fv.Elem() } // TODO store the field name in the field so // that we can produce a nice error message. if err := f.marshal(fv, p); err != nil { return errgo.WithCausef(err, ErrUnmarshal, "cannot marshal field") } } path, err := buildPath(p.Request.URL.Path, p.PathVar) if err != nil { return errgo.Mask(err) } p.Request.URL.Path = path if q := p.Request.Form.Encode(); q != "" && p.Request.URL.RawQuery != "" { p.Request.URL.RawQuery += "&" + q } else { p.Request.URL.RawQuery += q } return nil }
func marshalStruct(value reflect.Value) map[string]*dynamodb.AttributeValue { t := value.Type() numField := t.NumField() ret := make(map[string]*dynamodb.AttributeValue) for i := 0; i < numField; i++ { f := t.Field(i) if f.PkgPath != "" { continue } name, option := parseTag(f.Tag.Get("json")) if name == "-" { continue } if option == "omitifempty" { continue } if name == "" { name = f.Name } ret[name] = marshalValue(value.FieldByIndex(f.Index)) } return ret }
// unmarshalPaths walks down an XML structure looking for // wanted paths, and calls unmarshal on them. func (p *Parser) unmarshalPaths(sv reflect.Value, paths map[string]pathInfo, path string, start *StartElement) os.Error { if info, _ := paths[path]; info.complete { return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start) } for { tok, err := p.Token() if err != nil { return err } switch t := tok.(type) { case StartElement: k := path + ">" + fieldName(t.Name.Local) if _, found := paths[k]; found { if err := p.unmarshalPaths(sv, paths, k, &t); err != nil { return err } continue } if err := p.Skip(); err != nil { return err } case EndElement: return nil } } panic("unreachable") }
// oneStruct scans the result into a single struct type func (r Result) oneStruct(columns []string, elem reflect.Value, obj interface{}) error { fields := DeepFields(obj) aligned := AlignFields(columns, fields) // Create an interface pointer for each column's destination. // Unmatched scanner values will be discarded dest := make([]interface{}, len(columns)) // If nothing matched and the number of fields equals the number // columns, then blindly align columns and fields // TODO This may be too friendly of a feature if NoMatchingFields(aligned) && len(fields) == len(columns) { aligned = fields } for i, field := range aligned { if field.Exists() { dest[i] = elem.FieldByIndex(field.Type.Index).Addr().Interface() } else { dest[i] = &dest[i] // Discard } } if err := r.Scan(dest...); err != nil { return fmt.Errorf("sol: error scanning struct: %s", err) } return r.Err() // Check for delayed scan errors }
func (f Fields) Pack(buf []byte, val reflect.Value) error { for val.Kind() == reflect.Ptr { val = val.Elem() } pos := 0 for i, field := range f { if !field.CanSet { continue } v := val.Field(i) length := field.Len if field.Sizefrom != nil { length = int(val.FieldByIndex(field.Sizefrom).Int()) } if length <= 0 && field.Slice { length = field.Size(v) } if field.Sizeof != nil { length := val.FieldByIndex(field.Sizeof).Len() v = reflect.ValueOf(length) } err := field.Pack(buf[pos:], v, length) if err != nil { return err } pos += field.Size(v) } return nil }
// support multiple name casting: snake, lowercases func (m Master) getField(v reflect.Value, schema string) (f reflect.Value, pos int) { // TODO: indirect(v) here is overkill? names := strings.Split(schema, m.SchemaSeparator) for _, name := range names { v = indirect(v) if v.Kind() != reflect.Struct { break } num := v.NumField() vt := v.Type() for i := 0; i < num; i++ { sf := vt.FieldByIndex([]int{i}) options := strings.Split(sf.Tag.Get("sqlkungfu"), ",") if options[0] == name || strings.ToLower(sf.Name) == name { f = v.FieldByIndex([]int{i}) break } if indirectT(sf.Type).Kind() == reflect.Struct && (sf.Anonymous || optionsContain(options[1:], "inline") || len(names) > 1) { if f, _ = m.getField(v.FieldByIndex([]int{i}), name); f.IsValid() { break } } } if f.IsValid() { v = f pos++ continue } } return }
func flattenStruct(args Args, v reflect.Value) Args { ss := structSpecForType(v.Type()) for _, fs := range ss.l { fv := v.FieldByIndex(fs.index) if fv.CanAddr() { addr := fv.Addr().Interface() if ec, ok := addr.(gob.GobEncoder); ok { if buf, err := ec.GobEncode(); err == nil { args = append(args, fs.name, buf) return args } } else if ec, ok := addr.(json.Marshaler); ok { if buf, err := ec.MarshalJSON(); err == nil { args = append(args, fs.name, buf) return args } } else if ec, ok := addr.(encoding.BinaryMarshaler); ok { if buf, err := ec.MarshalBinary(); err != nil { args = append(args, fs.name, buf) return args } } } args = append(args, fs.name, fv.Interface()) } return args }
// isSameUnknownStruct returns true if the two struct values are the same length // and have the same contents as defined by IsSame. This function explicitly // ignores the declared type of the struct. func isSameStruct(x, y reflect.Value) bool { sx, okx := x.Interface().(StringConvertable) sy, oky := x.Interface().(StringConvertable) if okx && oky { //log.Println("Stringable", x, y) return sx.String() == sy.String() } numFields := x.NumField() if numFields != y.NumField() { return false } typeX := x.Type() for i := 0; i < numFields; i++ { path := []int{i} vx := x.FieldByIndex(path) vy := y.FieldByName(typeX.Field(i).Name) if vx.CanInterface() && vy.CanInterface() { if !IsSame(vx.Interface(), vy.Interface()) { return false } } } return true }
func walkStruct(v reflect.Value, w interface{}) (err error) { vt := v.Type() for i := 0; i < vt.NumField(); i++ { sf := vt.Field(i) f := v.FieldByIndex([]int{i}) if sw, ok := w.(StructWalker); ok { err = sw.StructField(sf, f) if err != nil { return } } ew, ok := w.(EnterExitWalker) if ok { ew.Enter(StructField) } err = walk(f, w) if err != nil { return } if ok { ew.Exit(StructField) } } return nil }
func GetColVals(val reflect.Value, cols []string) (values []string, err error) { typ := val.Type() // if not struct, then must just have one column. if val.Kind() != reflect.Struct && len(cols) != 1 { return nil, fmt.Errorf("GetColVals> If not a struct(%s), must have one column: %v", val.Kind(), cols) } values = make([]string, len(cols)) for i, col := range cols { var fieldVal reflect.Value if val.Kind() == reflect.Struct { fieldIndex := getFieldIndexByName(typ, col) if fieldIndex[0] < 0 { return nil, fmt.Errorf("GetColVals> Can't found struct field(column): '%s'\n", col) } fieldVal = val.FieldByIndex(fieldIndex) } else { fieldVal = val } if values[i], err = GetValQuoteStr(fieldVal); err != nil { return } } return }
// execute delete sql dbQuerier with given struct reflect.Value. // delete index is pk. func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { pkName, pkValue, ok := getExistPk(mi, ind) if ok == false { return 0, ErrMissPK } Q := d.ins.TableQuote() query := fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s = ?", Q, mi.table, Q, Q, pkName, Q) d.ins.ReplaceMarks(&query) res, err := q.Exec(query, pkValue) if err == nil { num, err := res.RowsAffected() if err != nil { return 0, err } if num > 0 { if mi.fields.pk.auto { if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 { ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(0) } else { ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(0) } } err := d.deleteRels(q, mi, []interface{}{pkValue}, tz) if err != nil { return num, err } } return num, err } return 0, err }
func (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value) error { // To maintain backwards compatibility with ConvertTo family of methods which // converted time.Time structs to strings if t, ok := v.Interface().(time.Time); ok { s := t.Format(time.RFC3339Nano) av.S = &s return nil } av.M = map[string]*dynamodb.AttributeValue{} fields := unionStructFields(v.Type(), e.MarshalOptions) for _, f := range fields { if f.Name == "" { return &InvalidMarshalError{msg: "map key cannot be empty"} } fv := v.FieldByIndex(f.Index) elem := &dynamodb.AttributeValue{} err := e.encode(elem, fv, f.tag) skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err) if err != nil { return err } else if skip { continue } av.M[f.Name] = elem } if len(av.M) == 0 { encodeNull(av) } return nil }
func (f *field) AppendValue(dst []byte, v reflect.Value, quote bool) []byte { fv := v.FieldByIndex(f.index) if f.Is(nullEmpty) && isEmptyValue(fv) { return appendNull(dst, quote) } return f.appender(dst, fv, quote) }
func (t *structType) HtmlView(v reflect.Value) (html template.HTML, err error) { err = t.init() if err != nil { return } type templateRow struct { Path string Name string Html template.HTML } var templateData []templateRow for _, sf := range t.fields { var thisHtml template.HTML thisHtml, err = sf.Type.HtmlView(v.FieldByIndex(sf.Index)) if err != nil { return } templateData = append(templateData, templateRow{ Path: sf.Name, Name: sf.Name, Html: thisHtml, }) } return theTemplate.ExecuteNameToHtml("Struct", templateData) }
func sliceKeys(mapper KeyMapper, val reflect.Value) (map[string]interface{}, error) { lookup := map[string]interface{}{} for i := 0; i < val.Len(); i++ { val := val.Index(i) // Get the key indexes and names for changes we care about. keyIndexes, err := mapper.KeyIndexes(val) if err != nil { return nil, err } // Loop over the key indexes and generate a key for each to match on. keyParts := []string{} for _, key := range keyIndexes.Keys { // Retrieve the field, and then append to the key parts. field := val.FieldByIndex(keyIndexes.Indexes[key]) switch fieldVal := field.Interface().(type) { case int, bool, float64, string, time.Time: keyParts = append(keyParts, fmt.Sprintf("%v", fieldVal)) break } } lookup[strings.Join(keyParts, ":")] = val.Interface() } return lookup, nil }
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 flattenStruct(args Args, v reflect.Value) Args { ss := structSpecForType(v.Type()) for _, fs := range ss.l { fv := v.FieldByIndex(fs.index) if fs.json { js, err := json.Marshal(fv.Interface()) if err != nil { log.Printf("redigo: WARNING: Failed to json marshal property %s error: %s", fs.name, err) } else { args = append(args, fs.name, string(js)) } } else { if fv.Kind() == reflect.Ptr { if fv.IsNil() { args = append(args, fs.name, fv.Interface()) } else { args = append(args, fs.name, fv.Elem().Interface()) } } else { args = append(args, fs.name, fv.Interface()) } } } return args }
func flattenStruct(args Args, v reflect.Value) Args { ss := structSpecForType(v.Type()) for _, fs := range ss.l { fv := v.FieldByIndex(fs.index) if fs.omitEmpty { var empty = false switch fv.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: empty = fv.Len() == 0 case reflect.Bool: empty = !fv.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: empty = fv.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: empty = fv.Uint() == 0 case reflect.Float32, reflect.Float64: empty = fv.Float() == 0 case reflect.Interface, reflect.Ptr: empty = fv.IsNil() } if empty { continue } } args = append(args, fs.name, fv.Interface()) } return args }
// evalField evaluates an expression like (.Field) or (.Field arg1 arg2). // The 'final' argument represents the return value from the preceding // value of the pipeline, if any. func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value { if !receiver.IsValid() { return zero } typ := receiver.Type() receiver, _ = indirect(receiver) // Unless it's an interface, need to get to a value of type *T to guarantee // we see all methods of T and *T. ptr := receiver if ptr.Kind() != reflect.Interface && ptr.CanAddr() { ptr = ptr.Addr() } if method := ptr.MethodByName(fieldName); method.IsValid() { return s.evalCall(dot, method, node, fieldName, args, final) } hasArgs := len(args) > 1 || final.IsValid() // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil. receiver, isNil := indirect(receiver) if isNil { s.errorf("nil pointer evaluating %s.%s", typ, fieldName) } switch receiver.Kind() { case reflect.Struct: tField, ok := receiver.Type().FieldByName(fieldName) if ok { field := receiver.FieldByIndex(tField.Index) if tField.PkgPath != "" { // field is unexported s.errorf("%s is an unexported field of struct type %s", fieldName, typ) } // If it's a function, we must call it. if hasArgs { s.errorf("%s has arguments but cannot be invoked as function", fieldName) } return field } s.errorf("%s is not a field of struct type %s", fieldName, typ) case reflect.Map: // If it's a map, attempt to use the field name as a key. nameVal := reflect.ValueOf(fieldName) if nameVal.Type().AssignableTo(receiver.Type().Key()) { if hasArgs { s.errorf("%s is not a method but has arguments", fieldName) } result := receiver.MapIndex(nameVal) if !result.IsValid() { switch s.tmpl.option.missingKey { case mapInvalid: // Just use the invalid value. case mapZeroValue: result = reflect.Zero(receiver.Type().Elem()) case mapError: s.errorf("map has no entry for key %q", fieldName) } } return result } } s.errorf("can't evaluate field %s in type %s", fieldName, typ) panic("not reached") }
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 (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value) error { av.M = map[string]*dynamodb.AttributeValue{} fields := unionStructFields(v.Type(), e.MarshalOptions) for _, f := range fields { if f.Name == "" { return &InvalidMarshalError{msg: "map key cannot be empty"} } fv := v.FieldByIndex(f.Index) elem := &dynamodb.AttributeValue{} err := e.encode(elem, fv, f.tag) skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err) if err != nil { return err } else if skip { continue } av.M[f.Name] = elem } if len(av.M) == 0 { encodeNull(av) } return nil }
// relatedEntityIDsFromStruct traverses a single struct instance for fields that // contain sideload ids. It adds those ids to the ids map if the ids are required. func relatedEntityIDsFromStruct(val reflect.Value, fields map[string][][]int, ids map[string]map[string]bool, required map[string]bool) { for entityName, indexes := range fields { // If we have required fields, and this entity isn't in it, skip this one. if len(required) > 0 && !required[entityName] { continue } for _, index := range indexes { // Get the field at the registered index. field := val.FieldByIndex(index) if field.Kind() == reflect.Ptr { field = field.Elem() } // Ensure it's a string type. if field.Kind() != reflect.String { continue } // Get the string value. id := field.String() if id == "" { continue } // Ensure we have a map for this entity type. if _, ok := ids[entityName]; !ok { ids[entityName] = map[string]bool{} } // Add the id. ids[entityName][id] = true } } }
// decodeStruct decodes a top-level struct and stores it in value. // Indir is for the value, not the type. At the time of the call it may // differ from ut.indir, which was computed when the engine was built. // This state cannot arise for decodeSingle, which is called directly // from the user's value, not from the innards of an engine. func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, value reflect.Value) { state := dec.newDecoderState(&dec.buf) defer dec.freeDecoderState(state) state.fieldnum = -1 for state.b.Len() > 0 { delta := int(state.decodeUint()) if delta < 0 { errorf("decode: corrupted data: negative delta") } if delta == 0 { // struct terminator is zero delta fieldnum break } fieldnum := state.fieldnum + delta if fieldnum >= len(engine.instr) { error_(errRange) break } instr := &engine.instr[fieldnum] var field reflect.Value if instr.index != nil { // Otherwise the field is unknown to us and instr.op is an ignore op. field = value.FieldByIndex(instr.index) if field.Kind() == reflect.Ptr { field = decAlloc(field) } } instr.op(instr, state, field) state.fieldnum = fieldnum } }
// unmarshalPath walks down an XML structure looking for wanted // paths, and calls unmarshal on them. // The consumed result tells whether XML elements have been consumed // from the Decoder until start's matching end element, or if it's // still untouched because start is uninteresting for sv's fields. func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) { recurse := false Loop: for i := range tinfo.fields { finfo := &tinfo.fields[i] if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) { continue } for j := range parents { if parents[j] != finfo.parents[j] { continue Loop } } if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local { // It's a perfect match, unmarshal the field. return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start) } if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local { // It's a prefix for the field. Break and recurse // since it's not ok for one field path to be itself // the prefix for another field path. recurse = true // We can reuse the same slice as long as we // don't try to append to it. parents = finfo.parents[:len(parents)+1] break } } if !recurse { // We have no business with this element. return false, nil } // The element is not a perfect match for any field, but one // or more fields have the path to this element as a parent // prefix. Recurse and attempt to match these. for { var tok Token tok, err = p.Token() if err != nil { return true, err } switch t := tok.(type) { case StartElement: consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t) if err != nil { return true, err } if !consumed2 { if err := p.Skip(); err != nil { return true, err } } case EndElement: return true, nil } } panic("unreachable") }
func (enc *Encoder) eStruct(key Key, rv reflect.Value) { // Write keys for fields directly under this key first, because if we write // a field that creates a new table, then all keys under it will be in that // table (not the one we're writing here). rt := rv.Type() var fieldsDirect, fieldsSub [][]int var addFields func(rt reflect.Type, rv reflect.Value, start []int) addFields = func(rt reflect.Type, rv reflect.Value, start []int) { for i := 0; i < rt.NumField(); i++ { f := rt.Field(i) // skip unexporded fields if f.PkgPath != "" { continue } frv := rv.Field(i) if f.Anonymous { frv := eindirect(frv) t := frv.Type() if t.Kind() != reflect.Struct { encPanic(errAnonNonStruct) } addFields(t, frv, f.Index) } else if typeIsHash(confTypeOfGo(frv)) { fieldsSub = append(fieldsSub, append(start, f.Index...)) } else { fieldsDirect = append(fieldsDirect, append(start, f.Index...)) } } } addFields(rt, rv, nil) var writeFields = func(fields [][]int) { for _, fieldIndex := range fields { sft := rt.FieldByIndex(fieldIndex) sf := rv.FieldByIndex(fieldIndex) if isNil(sf) { // Don't write anything for nil fields. continue } keyName := sft.Tag.Get("confl") if keyName == "-" { continue } if keyName == "" { keyName = sft.Tag.Get("json") if keyName == "-" { continue } else if keyName == "" { keyName = sft.Name } } //u.Infof("found key: depth?%v keyName='%v'\t\tsf=%v", len(key), keyName, sf) enc.encode(key.add(keyName), sf) } } writeFields(fieldsDirect) writeFields(fieldsSub) }
func marshalField(namespace string, s reflect.Value, f reflect.StructField) ([]byte, error) { switch field := s.FieldByIndex(f.Index); f.PkgPath { case "": // exported return marshalValue(path.Join(namespace, f.Name), field) default: // unexported return nil, nil } }
func flattenStruct(args Args, v reflect.Value) Args { ss := structSpecForType(v.Type()) for _, fs := range ss.l { fv := v.FieldByIndex(fs.index) args = append(args, fs.name, fv.Interface()) } return args }
func unmarshalField(form url.Values, namespace string, s reflect.Value, f reflect.StructField) error { switch field := s.FieldByIndex(f.Index); field.CanSet() { case false: // unexported return nil default: return unmarshalValue(form, field, path.Join(namespace, f.Name)) } }