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() }