2024-09-01 16:17:48 -04:00
|
|
|
package orm
|
|
|
|
|
2024-09-02 19:32:39 -04:00
|
|
|
import (
|
|
|
|
"fmt"
|
2024-09-04 19:43:12 -04:00
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
2024-09-02 19:32:39 -04:00
|
|
|
"reflect"
|
2024-09-05 13:57:35 -04:00
|
|
|
"regexp"
|
|
|
|
"strconv"
|
2024-09-02 19:32:39 -04:00
|
|
|
"strings"
|
|
|
|
)
|
2024-09-01 16:17:48 -04:00
|
|
|
|
|
|
|
func panik(err error) {
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func nameOf(i interface{}) string {
|
|
|
|
v := reflect.ValueOf(i)
|
|
|
|
var n string
|
|
|
|
switch v.Kind() {
|
|
|
|
case reflect.Slice, reflect.Map:
|
|
|
|
if v.Type().Elem().Kind() == reflect.Pointer {
|
|
|
|
n = v.Type().Elem().Elem().Name()
|
|
|
|
}
|
|
|
|
case reflect.Pointer:
|
|
|
|
n = nameOf(reflect.Indirect(v).Interface())
|
|
|
|
default:
|
|
|
|
n = v.Type().Name()
|
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func valueOf(i interface{}) reflect.Value {
|
|
|
|
v := reflect.ValueOf(i)
|
2024-09-03 00:14:12 -04:00
|
|
|
if v.Type().Kind() == reflect.Pointer {
|
2024-09-01 16:17:48 -04:00
|
|
|
v = valueOf(reflect.Indirect(v).Interface())
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func coerceInt(input reflect.Value, dst reflect.Value) interface{} {
|
|
|
|
if input.Type().Kind() == reflect.Pointer {
|
|
|
|
input = input.Elem()
|
|
|
|
}
|
|
|
|
if dst.Type().Kind() == reflect.Pointer {
|
|
|
|
dst = dst.Elem()
|
|
|
|
}
|
|
|
|
if input.Type().ConvertibleTo(dst.Type()) {
|
|
|
|
return input.Convert(dst.Type()).Interface()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2024-09-02 19:32:39 -04:00
|
|
|
|
2024-09-05 13:57:35 -04:00
|
|
|
var arrRegex, _ = regexp.Compile(`\[(?P<index>\d+)]$`)
|
|
|
|
|
2024-09-04 19:43:12 -04:00
|
|
|
func getNested(field string, value reflect.Value) (*reflect.StructField, *reflect.Value, error) {
|
2024-09-02 19:32:39 -04:00
|
|
|
if strings.HasPrefix(field, ".") || strings.HasSuffix(field, ".") {
|
|
|
|
return nil, nil, fmt.Errorf("Malformed field name %s passed", field)
|
|
|
|
}
|
|
|
|
dots := strings.Split(field, ".")
|
2024-09-05 13:57:35 -04:00
|
|
|
if value.Kind() != reflect.Struct && arrRegex.FindString(dots[0]) == "" {
|
2024-09-02 19:32:39 -04:00
|
|
|
return nil, nil, fmt.Errorf("This value is not a struct!")
|
|
|
|
}
|
|
|
|
ref := value
|
|
|
|
if ref.Kind() == reflect.Pointer {
|
|
|
|
ref = ref.Elem()
|
|
|
|
}
|
2024-09-05 13:57:35 -04:00
|
|
|
var fv reflect.Value = ref.FieldByName(arrRegex.ReplaceAllString(dots[0], ""))
|
|
|
|
if arrRegex.FindString(dots[0]) != "" && fv.Kind() == reflect.Slice {
|
|
|
|
matches := arrRegex.FindStringSubmatch(dots[0])
|
|
|
|
ridx, _ := strconv.Atoi(matches[0])
|
|
|
|
idx := int(ridx)
|
|
|
|
fv = fv.Index(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
ft, _ := ref.Type().FieldByName(arrRegex.ReplaceAllString(dots[0], ""))
|
2024-09-02 19:32:39 -04:00
|
|
|
if len(dots) > 1 {
|
|
|
|
return getNested(strings.Join(dots[1:], "."), fv)
|
|
|
|
} else {
|
|
|
|
return &ft, &fv, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func makeSettable(rval reflect.Value, value interface{}) reflect.Value {
|
|
|
|
if !rval.CanSet() {
|
|
|
|
nv := reflect.New(rval.Type())
|
|
|
|
nv.Elem().Set(reflect.ValueOf(value))
|
|
|
|
return nv
|
|
|
|
}
|
|
|
|
return rval
|
|
|
|
}
|
2024-09-04 19:43:12 -04:00
|
|
|
|
|
|
|
func incrementInterface(t interface{}) interface{} {
|
|
|
|
switch pt := t.(type) {
|
|
|
|
case uint:
|
|
|
|
t = pt + 1
|
|
|
|
case uint32:
|
|
|
|
t = pt + 1
|
|
|
|
case uint64:
|
|
|
|
t = pt + 1
|
|
|
|
case int:
|
|
|
|
t = pt + 1
|
|
|
|
case int32:
|
|
|
|
t = pt + 1
|
|
|
|
case int64:
|
|
|
|
t = pt + 1
|
|
|
|
case string:
|
|
|
|
t = NextStringID()
|
|
|
|
case primitive.ObjectID:
|
|
|
|
t = primitive.NewObjectID()
|
|
|
|
default:
|
|
|
|
panic("unknown or unsupported id type")
|
|
|
|
}
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
func pull(s reflect.Value, idx int, typ reflect.Type) reflect.Value {
|
|
|
|
retI := reflect.New(reflect.SliceOf(typ))
|
|
|
|
for i := 0; i < s.Len(); i++ {
|
|
|
|
if i == idx {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
retI.Elem().Set(reflect.Append(retI.Elem(), s.Index(i)))
|
|
|
|
}
|
|
|
|
return retI.Elem()
|
|
|
|
}
|
2024-09-05 13:57:35 -04:00
|
|
|
|
|
|
|
func checkStruct(ref reflect.Value) error {
|
|
|
|
if ref.Kind() == reflect.Slice {
|
|
|
|
return fmt.Errorf("Cannot append to multiple documents!")
|
|
|
|
}
|
|
|
|
if ref.Kind() != reflect.Struct {
|
|
|
|
return fmt.Errorf("Current object is not a struct!")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkSlice(ref reflect.Value) error {
|
|
|
|
if ref.Kind() != reflect.Slice {
|
|
|
|
return fmt.Errorf("Current field is not a slice!")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|