package urlstruct import ( "fmt" "reflect" "strings" "github.com/codemodus/kace" "github.com/go-pg/zerochecker" "github.com/vmihailenco/tagparser" ) type OpCode int const ( OpEq OpCode = iota + 1 OpNotEq OpLT OpLTE OpGT OpGTE OpIEq OpMatch ) type Field struct { Type reflect.Type Name string Index []int Tag *tagparser.Tag Column string Op OpCode noDecode bool required bool noWhere bool scanValue scannerFunc isZeroValue zerochecker.Func } func (f *Field) init() { _, f.required = f.Tag.Options["required"] _, f.noDecode = f.Tag.Options["nodecode"] _, f.noWhere = f.Tag.Options["nowhere"] if f.required && f.noWhere { err := fmt.Errorf("urlstruct: required and nowhere tags can't be set together") panic(err) } const sep = "_" f.Column, f.Op = splitColumnOperator(kace.Snake(f.Name), sep) if f.Type.Kind() == reflect.Slice { f.scanValue = sliceScanner(f.Type) } else { f.scanValue = scanner(f.Type) } f.isZeroValue = zerochecker.Checker(f.Type) } func (f *Field) Value(strct reflect.Value) reflect.Value { return strct.FieldByIndex(f.Index) } func (f *Field) Omit(value reflect.Value) bool { return !f.required && (f.noWhere || f.isZeroValue(value)) } func splitColumnOperator(s, sep string) (string, OpCode) { ind := strings.LastIndex(s, sep) if ind == -1 { return s, OpEq } col := s[:ind] op := s[ind+len(sep):] switch op { case "eq", "": return col, OpEq case "neq", "exclude": return col, OpNotEq case "gt": return col, OpGT case "gte": return col, OpGTE case "lt": return col, OpLT case "lte": return col, OpLTE case "ieq": return col, OpIEq case "match": return col, OpMatch default: return s, OpEq } }