summaryrefslogtreecommitdiff
path: root/vendor/github.com/uptrace/bun/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/uptrace/bun/util.go')
-rw-r--r--vendor/github.com/uptrace/bun/util.go114
1 files changed, 114 insertions, 0 deletions
diff --git a/vendor/github.com/uptrace/bun/util.go b/vendor/github.com/uptrace/bun/util.go
new file mode 100644
index 000000000..ce56be805
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/util.go
@@ -0,0 +1,114 @@
+package bun
+
+import "reflect"
+
+func indirect(v reflect.Value) reflect.Value {
+ switch v.Kind() {
+ case reflect.Interface:
+ return indirect(v.Elem())
+ case reflect.Ptr:
+ return v.Elem()
+ default:
+ return v
+ }
+}
+
+func walk(v reflect.Value, index []int, fn func(reflect.Value)) {
+ v = reflect.Indirect(v)
+ switch v.Kind() {
+ case reflect.Slice:
+ sliceLen := v.Len()
+ for i := 0; i < sliceLen; i++ {
+ visitField(v.Index(i), index, fn)
+ }
+ default:
+ visitField(v, index, fn)
+ }
+}
+
+func visitField(v reflect.Value, index []int, fn func(reflect.Value)) {
+ v = reflect.Indirect(v)
+ if len(index) > 0 {
+ v = v.Field(index[0])
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return
+ }
+ walk(v, index[1:], fn)
+ } else {
+ fn(v)
+ }
+}
+
+func typeByIndex(t reflect.Type, index []int) reflect.Type {
+ for _, x := range index {
+ switch t.Kind() {
+ case reflect.Ptr:
+ t = t.Elem()
+ case reflect.Slice:
+ t = indirectType(t.Elem())
+ }
+ t = t.Field(x).Type
+ }
+ return indirectType(t)
+}
+
+func indirectType(t reflect.Type) reflect.Type {
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ return t
+}
+
+func sliceElemType(v reflect.Value) reflect.Type {
+ elemType := v.Type().Elem()
+ if elemType.Kind() == reflect.Interface && v.Len() > 0 {
+ return indirect(v.Index(0).Elem()).Type()
+ }
+ return indirectType(elemType)
+}
+
+func makeSliceNextElemFunc(v reflect.Value) func() reflect.Value {
+ if v.Kind() == reflect.Array {
+ var pos int
+ return func() reflect.Value {
+ v := v.Index(pos)
+ pos++
+ return v
+ }
+ }
+
+ sliceType := v.Type()
+ elemType := sliceType.Elem()
+
+ if elemType.Kind() == reflect.Ptr {
+ elemType = elemType.Elem()
+ return func() reflect.Value {
+ if v.Len() < v.Cap() {
+ v.Set(v.Slice(0, v.Len()+1))
+ elem := v.Index(v.Len() - 1)
+ if elem.IsNil() {
+ elem.Set(reflect.New(elemType))
+ }
+ return elem.Elem()
+ }
+
+ elem := reflect.New(elemType)
+ v.Set(reflect.Append(v, elem))
+ return elem.Elem()
+ }
+ }
+
+ zero := reflect.Zero(elemType)
+ return func() reflect.Value {
+ l := v.Len()
+ c := v.Cap()
+
+ if l < c {
+ v.Set(v.Slice(0, l+1))
+ return v.Index(l)
+ }
+
+ v.Set(reflect.Append(v, zero))
+ return v.Index(l)
+ }
+}