-
Notifications
You must be signed in to change notification settings - Fork 3
/
column_type.go
170 lines (148 loc) · 6.45 KB
/
column_type.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package sif
// ColumnType is the base interface for all ColumnTypes.
// VariableWidthColumnType should be used for column types with
// unknown serialized width.
// FixedWidthColumnType should be used for columns types which
// have the additional property of known serialized width.
// Sif provides a variety of built-in ColumnTypes, and
// additional ColumnTypes may be added by implementing these
// interfaces
type ColumnType interface {
ToString(v interface{}) string // produces a string representation of a value of this Type
Deserialize([]byte) (interface{}, error) // Defines how this type is deserialized, returning an error if a value of the correct type could not be deserialized from the given bytes
}
// VariableWidthColumnType is an interface which is implemented
// to define a column type for variable-width data (where the
// serialized form has a varying size).
type VariableWidthColumnType interface {
ColumnType
Serialize(v interface{}) ([]byte, error) // Defines how this type is serialized, returning an error if the given value is not of the expected type, or if something went wrong during serialization
}
// FixedWidthColumnType is an interface which is implemented to define a
// column type for fixed-width data (at least the serialized form should
// be fixed-width). Sif provides a variety of built-in FixedWidthColumnTypes,
// and additional FixedWidthColumnTypes may be added by implementing this
// interface (in addition to GenericFixedWidthColumnType).
type FixedWidthColumnType interface {
ColumnType
Size() int // returns size in bytes of a column type
SerializeFixed(v interface{}, dest []byte) error // Similar to Serialize, but accepts a reusable buffer of guaranteed Size()
}
// GenericColumnType presents identical methods to ColumnType,
// but with typed variations as well. This interface makes for
// cleaner internal code for Sif, but is also intended
// to help future-proof the implementation of ColumnTypes
// (in the event that Golang ever considers adding covariance
// support to their generics implementation)
type GenericColumnType[T any] interface {
ColumnType
ToStringT(v T) string // produces a string representation of a value of this Type
DeserializeT([]byte) (T, error) // Defines how this type is deserialized, returning an error if a value of the correct type could not be deserialized from the given bytes
}
// GenericVariableWidthColumnType presents identical methods to
// VariableWidthColumnType, but with typed variations as well.
// This interface makes for cleaner internal code for Sif,
// but is also intended to help future-proof the
// implementation of FixedWidthColumnTypes (in the event
// that Golang ever considers adding covariance
// support to their generics implementation)
type GenericVariableWidthColumnType[T any] interface {
GenericColumnType[T]
VariableWidthColumnType
SerializeT(v T) ([]byte, error) // Similar to SerializeT, but accepts a reusable buffer of guaranteed Size()
}
// GenericFixedWidthColumnType presents identical methods to
// FixedWidthColumnType, but with typed variations as well.
// This interface makes for cleaner internal code for Sif,
// but is also intended to help future-proof the
// implementation of FixedWidthColumnTypes (in the event
// that Golang ever considers adding covariance
// support to their generics implementation)
type GenericFixedWidthColumnType[T any] interface {
GenericColumnType[T]
FixedWidthColumnType
SerializeFixedT(v T, dest []byte) error // Similar to SerializeT, but accepts a reusable buffer of guaranteed Size()
}
// ColumnAccessor defines the non-generic methods for
// a struct which can access data from a particular Column
// in a particular Row. Creators of custom column types
// should not typically need to implement their own
// ColumnAccessor, and can instead provide a factory
// function which calls CreateColumnAccessor instead.
type ColumnAccessor interface {
Name() string
String() string
Rename(newName string)
Clone() ColumnAccessor
Type() ColumnType
IsNil(row Row) bool // IsNil returns true iff the given column value is nil in this row. If an error occurs, this function will return false.
SetNil(row Row) error // SetNil sets the given column value to nil within this row
}
// GenericColumnAccessor defines the generic methods for
// a struct which can access data from a particular
// Column in a particular Row. Creators of custom column types
// should not typically need to implement their own
// GenericColumnAccessor, and can instead provide a factory
// function which calls CreateColumnAccessor instead.
type GenericColumnAccessor[T any] interface {
ColumnAccessor
CloneT() GenericColumnAccessor[T]
TypeT() GenericColumnType[T]
From(row Row) (T, error)
To(row Row, val T) error
}
// IsFixedWidth returns true iff colType is a FixedWidthColumnType
func IsFixedWidth(colType ColumnType) (isFixedWidth bool) {
_, isFixedWidth = colType.(FixedWidthColumnType)
return
}
type genericColumnAccessorImpl[T any] struct {
colType GenericColumnType[T]
colName string
}
func (a *genericColumnAccessorImpl[T]) Name() string {
return a.colName
}
func (a *genericColumnAccessorImpl[T]) String() string {
return a.Name()
}
func (a *genericColumnAccessorImpl[T]) Rename(newName string) {
a.colName = newName
}
func (a *genericColumnAccessorImpl[T]) Clone() ColumnAccessor {
return &genericColumnAccessorImpl[T]{colName: a.colName, colType: a.colType}
}
func (a *genericColumnAccessorImpl[T]) CloneT() GenericColumnAccessor[T] {
return &genericColumnAccessorImpl[T]{colName: a.colName, colType: a.colType}
}
func (a *genericColumnAccessorImpl[T]) TypeT() GenericColumnType[T] {
return a.colType
}
func (a *genericColumnAccessorImpl[T]) Type() ColumnType {
return a.colType
}
func (a *genericColumnAccessorImpl[T]) SetNil(row Row) error {
return row.SetNil(a.colName)
}
func (a *genericColumnAccessorImpl[T]) IsNil(row Row) bool {
return row.IsNil(a.colName)
}
func (a *genericColumnAccessorImpl[T]) From(row Row) (T, error) {
v, err := row.Get(a.colName)
if err != nil {
var zero T
return zero, err
}
return v.(T), nil
}
func (a *genericColumnAccessorImpl[T]) To(row Row, val T) error {
err := row.Set(a.colName, val)
if err != nil {
return err
}
return nil
}
// CreateColumnAccessor produces a GenericColumnAccessor for the given GenericColumnType
func CreateColumnAccessor[T any](colType GenericColumnType[T], colName string) GenericColumnAccessor[T] {
return &genericColumnAccessorImpl[T]{colType, colName}
}