156 lines
4.2 KiB
Go
156 lines
4.2 KiB
Go
|
package exerr
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"go.mongodb.org/mongo-driver/bson"
|
||
|
"go.mongodb.org/mongo-driver/bson/bsoncodec"
|
||
|
"go.mongodb.org/mongo-driver/bson/bsonrw"
|
||
|
"go.mongodb.org/mongo-driver/bson/bsontype"
|
||
|
"gogs.mikescher.com/BlackForestBytes/goext/dataext"
|
||
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||
|
"reflect"
|
||
|
)
|
||
|
|
||
|
type ErrorType struct {
|
||
|
Key string
|
||
|
DefaultStatusCode *int
|
||
|
}
|
||
|
|
||
|
//goland:noinspection GoUnusedGlobalVariable
|
||
|
var (
|
||
|
TypeInternal = NewType("INTERNAL_ERROR", langext.Ptr(500))
|
||
|
TypePanic = NewType("PANIC", langext.Ptr(500))
|
||
|
TypeNotImplemented = NewType("NOT_IMPLEMENTED", langext.Ptr(500))
|
||
|
|
||
|
TypeMongoQuery = NewType("MONGO_QUERY", langext.Ptr(500))
|
||
|
TypeCursorTokenDecode = NewType("CURSOR_TOKEN_DECODE", langext.Ptr(500))
|
||
|
TypeMongoFilter = NewType("MONGO_FILTER", langext.Ptr(500))
|
||
|
TypeMongoReflection = NewType("MONGO_REFLECTION", langext.Ptr(500))
|
||
|
TypeMongoInvalidOpt = NewType("MONGO_INVALIDOPT", langext.Ptr(500))
|
||
|
|
||
|
TypeSQLQuery = NewType("SQL_QUERY", langext.Ptr(500))
|
||
|
TypeSQLBuild = NewType("SQL_BUILD", langext.Ptr(500))
|
||
|
TypeSQLDecode = NewType("SQL_DECODE", langext.Ptr(500))
|
||
|
|
||
|
TypeWrap = NewType("Wrap", nil)
|
||
|
|
||
|
TypeBindFailURI = NewType("BINDFAIL_URI", langext.Ptr(400))
|
||
|
TypeBindFailQuery = NewType("BINDFAIL_QUERY", langext.Ptr(400))
|
||
|
TypeBindFailJSON = NewType("BINDFAIL_JSON", langext.Ptr(400))
|
||
|
TypeBindFailFormData = NewType("BINDFAIL_FORMDATA", langext.Ptr(400))
|
||
|
TypeBindFailHeader = NewType("BINDFAIL_HEADER", langext.Ptr(400))
|
||
|
|
||
|
TypeMarshalEntityID = NewType("MARSHAL_ENTITY_ID", langext.Ptr(400))
|
||
|
TypeInvalidCSID = NewType("INVALID_CSID", langext.Ptr(400))
|
||
|
|
||
|
TypeGoogleStatuscode = NewType("GOOGLE_STATUSCODE", langext.Ptr(400))
|
||
|
TypeGoogleResponse = NewType("GOOGLE_RESPONSE", langext.Ptr(400))
|
||
|
|
||
|
TypeUnauthorized = NewType("UNAUTHORIZED", langext.Ptr(401))
|
||
|
TypeAuthFailed = NewType("AUTH_FAILED", langext.Ptr(401))
|
||
|
|
||
|
TypeInvalidImage = NewType("IMAGEEXT_INVALID_IMAGE", langext.Ptr(400))
|
||
|
TypeInvalidMimeType = NewType("IMAGEEXT_INVALID_MIMETYPE", langext.Ptr(400))
|
||
|
|
||
|
// other values come from the downstream application that uses goext
|
||
|
)
|
||
|
|
||
|
func (e *ErrorType) UnmarshalJSON(bytes []byte) error {
|
||
|
var k string
|
||
|
err := json.Unmarshal(bytes, &k)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if d, ok := registeredTypes.Get(k); ok {
|
||
|
*e = d
|
||
|
return nil
|
||
|
} else {
|
||
|
*e = ErrorType{k, nil}
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (e ErrorType) MarshalJSON() ([]byte, error) {
|
||
|
return json.Marshal(e.Key)
|
||
|
}
|
||
|
|
||
|
func (e *ErrorType) UnmarshalBSONValue(bt bsontype.Type, data []byte) error {
|
||
|
if bt == bson.TypeNull {
|
||
|
// we can't set nil in UnmarshalBSONValue (so we use default(struct))
|
||
|
// Use mongoext.CreateGoExtBsonRegistry if you need to unmarsh pointer values
|
||
|
// https://stackoverflow.com/questions/75167597
|
||
|
// https://jira.mongodb.org/browse/GODRIVER-2252
|
||
|
*e = ErrorType{}
|
||
|
return nil
|
||
|
}
|
||
|
if bt != bson.TypeString {
|
||
|
return errors.New(fmt.Sprintf("cannot unmarshal %v into String", bt))
|
||
|
}
|
||
|
var tt string
|
||
|
err := bson.RawValue{Type: bt, Value: data}.Unmarshal(&tt)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if d, ok := registeredTypes.Get(tt); ok {
|
||
|
*e = d
|
||
|
return nil
|
||
|
} else {
|
||
|
*e = ErrorType{tt, nil}
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (e ErrorType) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
||
|
return bson.MarshalValue(e.Key)
|
||
|
}
|
||
|
|
||
|
func (e ErrorType) DecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
|
||
|
if val.Kind() == reflect.Ptr && val.IsNil() {
|
||
|
if !val.CanSet() {
|
||
|
return errors.New("ValueUnmarshalerDecodeValue")
|
||
|
}
|
||
|
val.Set(reflect.New(val.Type().Elem()))
|
||
|
}
|
||
|
|
||
|
tp, src, err := bsonrw.Copier{}.CopyValueToBytes(vr)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if val.Kind() == reflect.Ptr && len(src) == 0 {
|
||
|
val.Set(reflect.Zero(val.Type()))
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
err = e.UnmarshalBSONValue(tp, src)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if val.Kind() == reflect.Ptr {
|
||
|
val.Set(reflect.ValueOf(&e))
|
||
|
} else {
|
||
|
val.Set(reflect.ValueOf(e))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var registeredTypes = dataext.SyncMap[string, ErrorType]{}
|
||
|
|
||
|
func NewType(key string, defStatusCode *int) ErrorType {
|
||
|
et := ErrorType{key, defStatusCode}
|
||
|
|
||
|
registeredTypes.Set(key, et)
|
||
|
|
||
|
return et
|
||
|
}
|
||
|
|
||
|
func ListRegisteredTypes() []ErrorType {
|
||
|
return registeredTypes.GetAllValues()
|
||
|
}
|