diff options
| author | Niall Sheridan <nsheridan@gmail.com> | 2019-07-07 21:33:44 +0100 | 
|---|---|---|
| committer | Niall Sheridan <nsheridan@gmail.com> | 2019-07-07 21:33:44 +0100 | 
| commit | 8c12c6939aab9106db14ec2d11d983bc5b29fb2c (patch) | |
| tree | f9dc8a7d167c6355e47a65c52d4eb7b9ea03e6c8 /vendor/github.com/jmoiron/sqlx/reflectx | |
| parent | 0bd454cc448b812da6c693b451d86ff4cadbb6b2 (diff) | |
Switch to modules
Diffstat (limited to 'vendor/github.com/jmoiron/sqlx/reflectx')
| -rw-r--r-- | vendor/github.com/jmoiron/sqlx/reflectx/README.md | 17 | ||||
| -rw-r--r-- | vendor/github.com/jmoiron/sqlx/reflectx/reflect.go | 441 | 
2 files changed, 0 insertions, 458 deletions
diff --git a/vendor/github.com/jmoiron/sqlx/reflectx/README.md b/vendor/github.com/jmoiron/sqlx/reflectx/README.md deleted file mode 100644 index f01d3d1..0000000 --- a/vendor/github.com/jmoiron/sqlx/reflectx/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# reflectx - -The sqlx package has special reflect needs.  In particular, it needs to: - -* be able to map a name to a field -* understand embedded structs -* understand mapping names to fields by a particular tag -* user specified name -> field mapping functions - -These behaviors mimic the behaviors by the standard library marshallers and also the -behavior of standard Go accessors. - -The first two are amply taken care of by `Reflect.Value.FieldByName`, and the third is -addressed by `Reflect.Value.FieldByNameFunc`, but these don't quite understand struct -tags in the ways that are vital to most marshallers, and they are slow. - -This reflectx package extends reflect to achieve these goals. diff --git a/vendor/github.com/jmoiron/sqlx/reflectx/reflect.go b/vendor/github.com/jmoiron/sqlx/reflectx/reflect.go deleted file mode 100644 index 73c21eb..0000000 --- a/vendor/github.com/jmoiron/sqlx/reflectx/reflect.go +++ /dev/null @@ -1,441 +0,0 @@ -// Package reflectx implements extensions to the standard reflect lib suitable -// for implementing marshalling and unmarshalling packages.  The main Mapper type -// allows for Go-compatible named attribute access, including accessing embedded -// struct attributes and the ability to use  functions and struct tags to -// customize field names. -// -package reflectx - -import ( -	"reflect" -	"runtime" -	"strings" -	"sync" -) - -// A FieldInfo is metadata for a struct field. -type FieldInfo struct { -	Index    []int -	Path     string -	Field    reflect.StructField -	Zero     reflect.Value -	Name     string -	Options  map[string]string -	Embedded bool -	Children []*FieldInfo -	Parent   *FieldInfo -} - -// A StructMap is an index of field metadata for a struct. -type StructMap struct { -	Tree  *FieldInfo -	Index []*FieldInfo -	Paths map[string]*FieldInfo -	Names map[string]*FieldInfo -} - -// GetByPath returns a *FieldInfo for a given string path. -func (f StructMap) GetByPath(path string) *FieldInfo { -	return f.Paths[path] -} - -// GetByTraversal returns a *FieldInfo for a given integer path.  It is -// analogous to reflect.FieldByIndex, but using the cached traversal -// rather than re-executing the reflect machinery each time. -func (f StructMap) GetByTraversal(index []int) *FieldInfo { -	if len(index) == 0 { -		return nil -	} - -	tree := f.Tree -	for _, i := range index { -		if i >= len(tree.Children) || tree.Children[i] == nil { -			return nil -		} -		tree = tree.Children[i] -	} -	return tree -} - -// Mapper is a general purpose mapper of names to struct fields.  A Mapper -// behaves like most marshallers in the standard library, obeying a field tag -// for name mapping but also providing a basic transform function. -type Mapper struct { -	cache      map[reflect.Type]*StructMap -	tagName    string -	tagMapFunc func(string) string -	mapFunc    func(string) string -	mutex      sync.Mutex -} - -// NewMapper returns a new mapper using the tagName as its struct field tag. -// If tagName is the empty string, it is ignored. -func NewMapper(tagName string) *Mapper { -	return &Mapper{ -		cache:   make(map[reflect.Type]*StructMap), -		tagName: tagName, -	} -} - -// NewMapperTagFunc returns a new mapper which contains a mapper for field names -// AND a mapper for tag values.  This is useful for tags like json which can -// have values like "name,omitempty". -func NewMapperTagFunc(tagName string, mapFunc, tagMapFunc func(string) string) *Mapper { -	return &Mapper{ -		cache:      make(map[reflect.Type]*StructMap), -		tagName:    tagName, -		mapFunc:    mapFunc, -		tagMapFunc: tagMapFunc, -	} -} - -// NewMapperFunc returns a new mapper which optionally obeys a field tag and -// a struct field name mapper func given by f.  Tags will take precedence, but -// for any other field, the mapped name will be f(field.Name) -func NewMapperFunc(tagName string, f func(string) string) *Mapper { -	return &Mapper{ -		cache:   make(map[reflect.Type]*StructMap), -		tagName: tagName, -		mapFunc: f, -	} -} - -// TypeMap returns a mapping of field strings to int slices representing -// the traversal down the struct to reach the field. -func (m *Mapper) TypeMap(t reflect.Type) *StructMap { -	m.mutex.Lock() -	mapping, ok := m.cache[t] -	if !ok { -		mapping = getMapping(t, m.tagName, m.mapFunc, m.tagMapFunc) -		m.cache[t] = mapping -	} -	m.mutex.Unlock() -	return mapping -} - -// FieldMap returns the mapper's mapping of field names to reflect values.  Panics -// if v's Kind is not Struct, or v is not Indirectable to a struct kind. -func (m *Mapper) FieldMap(v reflect.Value) map[string]reflect.Value { -	v = reflect.Indirect(v) -	mustBe(v, reflect.Struct) - -	r := map[string]reflect.Value{} -	tm := m.TypeMap(v.Type()) -	for tagName, fi := range tm.Names { -		r[tagName] = FieldByIndexes(v, fi.Index) -	} -	return r -} - -// FieldByName returns a field by its mapped name as a reflect.Value. -// Panics if v's Kind is not Struct or v is not Indirectable to a struct Kind. -// Returns zero Value if the name is not found. -func (m *Mapper) FieldByName(v reflect.Value, name string) reflect.Value { -	v = reflect.Indirect(v) -	mustBe(v, reflect.Struct) - -	tm := m.TypeMap(v.Type()) -	fi, ok := tm.Names[name] -	if !ok { -		return v -	} -	return FieldByIndexes(v, fi.Index) -} - -// FieldsByName returns a slice of values corresponding to the slice of names -// for the value.  Panics if v's Kind is not Struct or v is not Indirectable -// to a struct Kind.  Returns zero Value for each name not found. -func (m *Mapper) FieldsByName(v reflect.Value, names []string) []reflect.Value { -	v = reflect.Indirect(v) -	mustBe(v, reflect.Struct) - -	tm := m.TypeMap(v.Type()) -	vals := make([]reflect.Value, 0, len(names)) -	for _, name := range names { -		fi, ok := tm.Names[name] -		if !ok { -			vals = append(vals, *new(reflect.Value)) -		} else { -			vals = append(vals, FieldByIndexes(v, fi.Index)) -		} -	} -	return vals -} - -// TraversalsByName returns a slice of int slices which represent the struct -// traversals for each mapped name.  Panics if t is not a struct or Indirectable -// to a struct.  Returns empty int slice for each name not found. -func (m *Mapper) TraversalsByName(t reflect.Type, names []string) [][]int { -	r := make([][]int, 0, len(names)) -	m.TraversalsByNameFunc(t, names, func(_ int, i []int) error { -		if i == nil { -			r = append(r, []int{}) -		} else { -			r = append(r, i) -		} - -		return nil -	}) -	return r -} - -// TraversalsByNameFunc traverses the mapped names and calls fn with the index of -// each name and the struct traversal represented by that name. Panics if t is not -// a struct or Indirectable to a struct. Returns the first error returned by fn or nil. -func (m *Mapper) TraversalsByNameFunc(t reflect.Type, names []string, fn func(int, []int) error) error { -	t = Deref(t) -	mustBe(t, reflect.Struct) -	tm := m.TypeMap(t) -	for i, name := range names { -		fi, ok := tm.Names[name] -		if !ok { -			if err := fn(i, nil); err != nil { -				return err -			} -		} else { -			if err := fn(i, fi.Index); err != nil { -				return err -			} -		} -	} -	return nil -} - -// FieldByIndexes returns a value for the field given by the struct traversal -// for the given value. -func FieldByIndexes(v reflect.Value, indexes []int) reflect.Value { -	for _, i := range indexes { -		v = reflect.Indirect(v).Field(i) -		// if this is a pointer and it's nil, allocate a new value and set it -		if v.Kind() == reflect.Ptr && v.IsNil() { -			alloc := reflect.New(Deref(v.Type())) -			v.Set(alloc) -		} -		if v.Kind() == reflect.Map && v.IsNil() { -			v.Set(reflect.MakeMap(v.Type())) -		} -	} -	return v -} - -// FieldByIndexesReadOnly returns a value for a particular struct traversal, -// but is not concerned with allocating nil pointers because the value is -// going to be used for reading and not setting. -func FieldByIndexesReadOnly(v reflect.Value, indexes []int) reflect.Value { -	for _, i := range indexes { -		v = reflect.Indirect(v).Field(i) -	} -	return v -} - -// Deref is Indirect for reflect.Types -func Deref(t reflect.Type) reflect.Type { -	if t.Kind() == reflect.Ptr { -		t = t.Elem() -	} -	return t -} - -// -- helpers & utilities -- - -type kinder interface { -	Kind() reflect.Kind -} - -// mustBe checks a value against a kind, panicing with a reflect.ValueError -// if the kind isn't that which is required. -func mustBe(v kinder, expected reflect.Kind) { -	if k := v.Kind(); k != expected { -		panic(&reflect.ValueError{Method: methodName(), Kind: k}) -	} -} - -// methodName returns the caller of the function calling methodName -func methodName() string { -	pc, _, _, _ := runtime.Caller(2) -	f := runtime.FuncForPC(pc) -	if f == nil { -		return "unknown method" -	} -	return f.Name() -} - -type typeQueue struct { -	t  reflect.Type -	fi *FieldInfo -	pp string // Parent path -} - -// A copying append that creates a new slice each time. -func apnd(is []int, i int) []int { -	x := make([]int, len(is)+1) -	for p, n := range is { -		x[p] = n -	} -	x[len(x)-1] = i -	return x -} - -type mapf func(string) string - -// parseName parses the tag and the target name for the given field using -// the tagName (eg 'json' for `json:"foo"` tags), mapFunc for mapping the -// field's name to a target name, and tagMapFunc for mapping the tag to -// a target name. -func parseName(field reflect.StructField, tagName string, mapFunc, tagMapFunc mapf) (tag, fieldName string) { -	// first, set the fieldName to the field's name -	fieldName = field.Name -	// if a mapFunc is set, use that to override the fieldName -	if mapFunc != nil { -		fieldName = mapFunc(fieldName) -	} - -	// if there's no tag to look for, return the field name -	if tagName == "" { -		return "", fieldName -	} - -	// if this tag is not set using the normal convention in the tag, -	// then return the fieldname..  this check is done because according -	// to the reflect documentation: -	//    If the tag does not have the conventional format, -	//    the value returned by Get is unspecified. -	// which doesn't sound great. -	if !strings.Contains(string(field.Tag), tagName+":") { -		return "", fieldName -	} - -	// at this point we're fairly sure that we have a tag, so lets pull it out -	tag = field.Tag.Get(tagName) - -	// if we have a mapper function, call it on the whole tag -	// XXX: this is a change from the old version, which pulled out the name -	// before the tagMapFunc could be run, but I think this is the right way -	if tagMapFunc != nil { -		tag = tagMapFunc(tag) -	} - -	// finally, split the options from the name -	parts := strings.Split(tag, ",") -	fieldName = parts[0] - -	return tag, fieldName -} - -// parseOptions parses options out of a tag string, skipping the name -func parseOptions(tag string) map[string]string { -	parts := strings.Split(tag, ",") -	options := make(map[string]string, len(parts)) -	if len(parts) > 1 { -		for _, opt := range parts[1:] { -			// short circuit potentially expensive split op -			if strings.Contains(opt, "=") { -				kv := strings.Split(opt, "=") -				options[kv[0]] = kv[1] -				continue -			} -			options[opt] = "" -		} -	} -	return options -} - -// getMapping returns a mapping for the t type, using the tagName, mapFunc and -// tagMapFunc to determine the canonical names of fields. -func getMapping(t reflect.Type, tagName string, mapFunc, tagMapFunc mapf) *StructMap { -	m := []*FieldInfo{} - -	root := &FieldInfo{} -	queue := []typeQueue{} -	queue = append(queue, typeQueue{Deref(t), root, ""}) - -QueueLoop: -	for len(queue) != 0 { -		// pop the first item off of the queue -		tq := queue[0] -		queue = queue[1:] - -		// ignore recursive field -		for p := tq.fi.Parent; p != nil; p = p.Parent { -			if tq.fi.Field.Type == p.Field.Type { -				continue QueueLoop -			} -		} - -		nChildren := 0 -		if tq.t.Kind() == reflect.Struct { -			nChildren = tq.t.NumField() -		} -		tq.fi.Children = make([]*FieldInfo, nChildren) - -		// iterate through all of its fields -		for fieldPos := 0; fieldPos < nChildren; fieldPos++ { - -			f := tq.t.Field(fieldPos) - -			// parse the tag and the target name using the mapping options for this field -			tag, name := parseName(f, tagName, mapFunc, tagMapFunc) - -			// if the name is "-", disabled via a tag, skip it -			if name == "-" { -				continue -			} - -			fi := FieldInfo{ -				Field:   f, -				Name:    name, -				Zero:    reflect.New(f.Type).Elem(), -				Options: parseOptions(tag), -			} - -			// if the path is empty this path is just the name -			if tq.pp == "" { -				fi.Path = fi.Name -			} else { -				fi.Path = tq.pp + "." + fi.Name -			} - -			// skip unexported fields -			if len(f.PkgPath) != 0 && !f.Anonymous { -				continue -			} - -			// bfs search of anonymous embedded structs -			if f.Anonymous { -				pp := tq.pp -				if tag != "" { -					pp = fi.Path -				} - -				fi.Embedded = true -				fi.Index = apnd(tq.fi.Index, fieldPos) -				nChildren := 0 -				ft := Deref(f.Type) -				if ft.Kind() == reflect.Struct { -					nChildren = ft.NumField() -				} -				fi.Children = make([]*FieldInfo, nChildren) -				queue = append(queue, typeQueue{Deref(f.Type), &fi, pp}) -			} else if fi.Zero.Kind() == reflect.Struct || (fi.Zero.Kind() == reflect.Ptr && fi.Zero.Type().Elem().Kind() == reflect.Struct) { -				fi.Index = apnd(tq.fi.Index, fieldPos) -				fi.Children = make([]*FieldInfo, Deref(f.Type).NumField()) -				queue = append(queue, typeQueue{Deref(f.Type), &fi, fi.Path}) -			} - -			fi.Index = apnd(tq.fi.Index, fieldPos) -			fi.Parent = tq.fi -			tq.fi.Children[fieldPos] = &fi -			m = append(m, &fi) -		} -	} - -	flds := &StructMap{Index: m, Tree: root, Paths: map[string]*FieldInfo{}, Names: map[string]*FieldInfo{}} -	for _, fi := range flds.Index { -		flds.Paths[fi.Path] = fi -		if fi.Name != "" && !fi.Embedded { -			flds.Names[fi.Path] = fi -		} -	} - -	return flds -}  | 
