-
Notifications
You must be signed in to change notification settings - Fork 9
/
record.go
99 lines (86 loc) · 2.6 KB
/
record.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
* Copyright 2018. bigpigeon. All rights reserved.
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*/
package toyorm
import (
"reflect"
)
type ModelRecordFieldTypes interface {
GetFieldType(field string) reflect.Type
}
type ModelRecord interface {
AllField() map[string]reflect.Value
SetField(field string, v reflect.Value)
DeleteField(string)
Field(field string) reflect.Value
FieldAddress(field string) reflect.Value
IsVariableContainer() bool
Source() reflect.Value
GetFieldType(string) reflect.Type
}
type ModelIndexRecord struct {
ModelRecord
Index int
}
type ModelGroupBy map[interface{}][]ModelIndexRecord
func (m ModelGroupBy) Keys() []interface{} {
l := make([]interface{}, 0, len(m))
for k := range m {
l = append(l, k)
}
return l
}
type ModelRecords interface {
GetRecord(int) ModelRecord
GetRecords() []ModelRecord
Add(v reflect.Value) ModelRecord
GetFieldType(string) reflect.Type
GetFieldAddressType(string) reflect.Type
IsVariableContainer() bool
ElemType() reflect.Type
Len() int
Source() reflect.Value
GroupBy(key string) ModelGroupBy
}
func NewRecords(model *Model, value reflect.Value) ModelRecords {
if value.Kind() != reflect.Slice {
panic("value must be slice")
}
elemType := LoopTypeIndirectSliceAndPtr(value.Type())
if _, ok := reflect.Zero(elemType).Interface().(map[string]interface{}); ok {
return NewNameMapRecords(model, value)
} else if _, ok := reflect.Zero(elemType).Interface().(map[uintptr]interface{}); ok {
return NewOffsetMapRecords(model, value)
} else if elemType.Kind() == reflect.Struct {
return NewStructRecords(model, value)
} else {
panic(ErrInvalidRecordType{})
}
}
func NewRecord(model *Model, value reflect.Value) ModelRecord {
vType := LoopTypeIndirect(value.Type())
if _, ok := reflect.Zero(vType).Interface().(map[string]interface{}); ok {
return NewNameMapRecord(model, value)
} else if _, ok := reflect.Zero(vType).Interface().(map[uintptr]interface{}); ok {
return NewOffsetMapRecord(model, value)
} else if vType.Kind() == reflect.Struct {
return NewStructRecord(model, value)
} else {
panic(ErrInvalidRecordType{})
}
}
// use element type to create ModelRecords
func MakeRecordsWithElem(model *Model, _type reflect.Type) ModelRecords {
v := reflect.New(reflect.SliceOf(_type)).Elem()
return NewRecords(model, v)
}
func MakeRecords(model *Model, _type reflect.Type) ModelRecords {
v := reflect.New(_type).Elem()
return NewRecords(model, v)
}
func MakeRecord(model *Model, _type reflect.Type) ModelRecord {
v := reflect.New(_type).Elem()
return NewRecord(model, v)
}