diamond-orm/util.go
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 924b3fc9d2
many additions!
- add support for `autoinc` struct tag
- add Pull method to Model
- add utility func to increment a value of an unknown type by 1
- idcounter.go no longer increments the counter value (it is now up to the caller to increment the returned value themselves)
2024-09-04 19:43:12 -04:00

132 lines
2.8 KiB
Go

package orm
import (
"fmt"
"go.mongodb.org/mongo-driver/bson/primitive"
"reflect"
"strings"
)
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)
if v.Type().Kind() == reflect.Pointer {
v = valueOf(reflect.Indirect(v).Interface())
}
return v
}
func iFace(input interface{}) interface{} {
return reflect.ValueOf(input).Interface()
}
func iFaceSlice(input interface{}) []interface{} {
ret := make([]interface{}, 0)
fv := reflect.ValueOf(input)
if fv.Type().Kind() != reflect.Slice {
return ret
}
for i := 0; i < fv.Len(); i++ {
ret = append(ret, fv.Index(i).Interface())
}
return ret
}
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
}
func getNested(field string, value reflect.Value) (*reflect.StructField, *reflect.Value, error) {
if strings.HasPrefix(field, ".") || strings.HasSuffix(field, ".") {
return nil, nil, fmt.Errorf("Malformed field name %s passed", field)
}
dots := strings.Split(field, ".")
if value.Kind() != reflect.Struct {
return nil, nil, fmt.Errorf("This value is not a struct!")
}
ref := value
if ref.Kind() == reflect.Pointer {
ref = ref.Elem()
}
fv := ref.FieldByName(dots[0])
ft, _ := ref.Type().FieldByName(dots[0])
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
}
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()
}