podman

Форк
0
299 строк · 6.7 Кб
1
// Extracted from Go database/sql source code
2

3
// Copyright 2011 The Go Authors. All rights reserved.
4
// Use of this source code is governed by a BSD-style
5
// license that can be found in the LICENSE file.
6

7
// Type conversions for Scan.
8

9
package sqlite3
10

11
import (
12
	"database/sql"
13
	"database/sql/driver"
14
	"errors"
15
	"fmt"
16
	"reflect"
17
	"strconv"
18
	"time"
19
)
20

21
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
22

23
// convertAssign copies to dest the value in src, converting it if possible.
24
// An error is returned if the copy would result in loss of information.
25
// dest should be a pointer type.
26
func convertAssign(dest, src any) error {
27
	// Common cases, without reflect.
28
	switch s := src.(type) {
29
	case string:
30
		switch d := dest.(type) {
31
		case *string:
32
			if d == nil {
33
				return errNilPtr
34
			}
35
			*d = s
36
			return nil
37
		case *[]byte:
38
			if d == nil {
39
				return errNilPtr
40
			}
41
			*d = []byte(s)
42
			return nil
43
		case *sql.RawBytes:
44
			if d == nil {
45
				return errNilPtr
46
			}
47
			*d = append((*d)[:0], s...)
48
			return nil
49
		}
50
	case []byte:
51
		switch d := dest.(type) {
52
		case *string:
53
			if d == nil {
54
				return errNilPtr
55
			}
56
			*d = string(s)
57
			return nil
58
		case *any:
59
			if d == nil {
60
				return errNilPtr
61
			}
62
			*d = cloneBytes(s)
63
			return nil
64
		case *[]byte:
65
			if d == nil {
66
				return errNilPtr
67
			}
68
			*d = cloneBytes(s)
69
			return nil
70
		case *sql.RawBytes:
71
			if d == nil {
72
				return errNilPtr
73
			}
74
			*d = s
75
			return nil
76
		}
77
	case time.Time:
78
		switch d := dest.(type) {
79
		case *time.Time:
80
			*d = s
81
			return nil
82
		case *string:
83
			*d = s.Format(time.RFC3339Nano)
84
			return nil
85
		case *[]byte:
86
			if d == nil {
87
				return errNilPtr
88
			}
89
			*d = []byte(s.Format(time.RFC3339Nano))
90
			return nil
91
		case *sql.RawBytes:
92
			if d == nil {
93
				return errNilPtr
94
			}
95
			*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
96
			return nil
97
		}
98
	case nil:
99
		switch d := dest.(type) {
100
		case *any:
101
			if d == nil {
102
				return errNilPtr
103
			}
104
			*d = nil
105
			return nil
106
		case *[]byte:
107
			if d == nil {
108
				return errNilPtr
109
			}
110
			*d = nil
111
			return nil
112
		case *sql.RawBytes:
113
			if d == nil {
114
				return errNilPtr
115
			}
116
			*d = nil
117
			return nil
118
		}
119
	}
120

121
	var sv reflect.Value
122

123
	switch d := dest.(type) {
124
	case *string:
125
		sv = reflect.ValueOf(src)
126
		switch sv.Kind() {
127
		case reflect.Bool,
128
			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
129
			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
130
			reflect.Float32, reflect.Float64:
131
			*d = asString(src)
132
			return nil
133
		}
134
	case *[]byte:
135
		sv = reflect.ValueOf(src)
136
		if b, ok := asBytes(nil, sv); ok {
137
			*d = b
138
			return nil
139
		}
140
	case *sql.RawBytes:
141
		sv = reflect.ValueOf(src)
142
		if b, ok := asBytes([]byte(*d)[:0], sv); ok {
143
			*d = sql.RawBytes(b)
144
			return nil
145
		}
146
	case *bool:
147
		bv, err := driver.Bool.ConvertValue(src)
148
		if err == nil {
149
			*d = bv.(bool)
150
		}
151
		return err
152
	case *any:
153
		*d = src
154
		return nil
155
	}
156

157
	if scanner, ok := dest.(sql.Scanner); ok {
158
		return scanner.Scan(src)
159
	}
160

161
	dpv := reflect.ValueOf(dest)
162
	if dpv.Kind() != reflect.Ptr {
163
		return errors.New("destination not a pointer")
164
	}
165
	if dpv.IsNil() {
166
		return errNilPtr
167
	}
168

169
	if !sv.IsValid() {
170
		sv = reflect.ValueOf(src)
171
	}
172

173
	dv := reflect.Indirect(dpv)
174
	if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
175
		switch b := src.(type) {
176
		case []byte:
177
			dv.Set(reflect.ValueOf(cloneBytes(b)))
178
		default:
179
			dv.Set(sv)
180
		}
181
		return nil
182
	}
183

184
	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
185
		dv.Set(sv.Convert(dv.Type()))
186
		return nil
187
	}
188

189
	// The following conversions use a string value as an intermediate representation
190
	// to convert between various numeric types.
191
	//
192
	// This also allows scanning into user defined types such as "type Int int64".
193
	// For symmetry, also check for string destination types.
194
	switch dv.Kind() {
195
	case reflect.Ptr:
196
		if src == nil {
197
			dv.Set(reflect.Zero(dv.Type()))
198
			return nil
199
		}
200
		dv.Set(reflect.New(dv.Type().Elem()))
201
		return convertAssign(dv.Interface(), src)
202
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
203
		s := asString(src)
204
		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
205
		if err != nil {
206
			err = strconvErr(err)
207
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
208
		}
209
		dv.SetInt(i64)
210
		return nil
211
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
212
		s := asString(src)
213
		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
214
		if err != nil {
215
			err = strconvErr(err)
216
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
217
		}
218
		dv.SetUint(u64)
219
		return nil
220
	case reflect.Float32, reflect.Float64:
221
		s := asString(src)
222
		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
223
		if err != nil {
224
			err = strconvErr(err)
225
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
226
		}
227
		dv.SetFloat(f64)
228
		return nil
229
	case reflect.String:
230
		switch v := src.(type) {
231
		case string:
232
			dv.SetString(v)
233
			return nil
234
		case []byte:
235
			dv.SetString(string(v))
236
			return nil
237
		}
238
	}
239

240
	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
241
}
242

243
func strconvErr(err error) error {
244
	if ne, ok := err.(*strconv.NumError); ok {
245
		return ne.Err
246
	}
247
	return err
248
}
249

250
func cloneBytes(b []byte) []byte {
251
	if b == nil {
252
		return nil
253
	}
254
	c := make([]byte, len(b))
255
	copy(c, b)
256
	return c
257
}
258

259
func asString(src any) string {
260
	switch v := src.(type) {
261
	case string:
262
		return v
263
	case []byte:
264
		return string(v)
265
	}
266
	rv := reflect.ValueOf(src)
267
	switch rv.Kind() {
268
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
269
		return strconv.FormatInt(rv.Int(), 10)
270
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
271
		return strconv.FormatUint(rv.Uint(), 10)
272
	case reflect.Float64:
273
		return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
274
	case reflect.Float32:
275
		return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
276
	case reflect.Bool:
277
		return strconv.FormatBool(rv.Bool())
278
	}
279
	return fmt.Sprintf("%v", src)
280
}
281

282
func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
283
	switch rv.Kind() {
284
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
285
		return strconv.AppendInt(buf, rv.Int(), 10), true
286
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
287
		return strconv.AppendUint(buf, rv.Uint(), 10), true
288
	case reflect.Float32:
289
		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
290
	case reflect.Float64:
291
		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
292
	case reflect.Bool:
293
		return strconv.AppendBool(buf, rv.Bool()), true
294
	case reflect.String:
295
		s := rv.String()
296
		return append(buf, s...), true
297
	}
298
	return
299
}
300

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.