go-tg-screenshot-bot

Форк
0
430 строк · 10.6 Кб
1
package dbus
2

3
import (
4
	"errors"
5
	"fmt"
6
	"reflect"
7
	"strings"
8
)
9

10
var (
11
	byteType        = reflect.TypeOf(byte(0))
12
	boolType        = reflect.TypeOf(false)
13
	uint8Type       = reflect.TypeOf(uint8(0))
14
	int16Type       = reflect.TypeOf(int16(0))
15
	uint16Type      = reflect.TypeOf(uint16(0))
16
	intType         = reflect.TypeOf(int(0))
17
	uintType        = reflect.TypeOf(uint(0))
18
	int32Type       = reflect.TypeOf(int32(0))
19
	uint32Type      = reflect.TypeOf(uint32(0))
20
	int64Type       = reflect.TypeOf(int64(0))
21
	uint64Type      = reflect.TypeOf(uint64(0))
22
	float64Type     = reflect.TypeOf(float64(0))
23
	stringType      = reflect.TypeOf("")
24
	signatureType   = reflect.TypeOf(Signature{""})
25
	objectPathType  = reflect.TypeOf(ObjectPath(""))
26
	variantType     = reflect.TypeOf(Variant{Signature{""}, nil})
27
	interfacesType  = reflect.TypeOf([]interface{}{})
28
	interfaceType   = reflect.TypeOf((*interface{})(nil)).Elem()
29
	unixFDType      = reflect.TypeOf(UnixFD(0))
30
	unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
31
	errType         = reflect.TypeOf((*error)(nil)).Elem()
32
)
33

34
// An InvalidTypeError signals that a value which cannot be represented in the
35
// D-Bus wire format was passed to a function.
36
type InvalidTypeError struct {
37
	Type reflect.Type
38
}
39

40
func (e InvalidTypeError) Error() string {
41
	return "dbus: invalid type " + e.Type.String()
42
}
43

44
// Store copies the values contained in src to dest, which must be a slice of
45
// pointers. It converts slices of interfaces from src to corresponding structs
46
// in dest. An error is returned if the lengths of src and dest or the types of
47
// their elements don't match.
48
func Store(src []interface{}, dest ...interface{}) error {
49
	if len(src) != len(dest) {
50
		return errors.New("dbus.Store: length mismatch")
51
	}
52

53
	for i := range src {
54
		if err := storeInterfaces(src[i], dest[i]); err != nil {
55
			return err
56
		}
57
	}
58
	return nil
59
}
60

61
func storeInterfaces(src, dest interface{}) error {
62
	return store(reflect.ValueOf(dest), reflect.ValueOf(src))
63
}
64

65
func store(dest, src reflect.Value) error {
66
	if dest.Kind() == reflect.Ptr {
67
		if dest.IsNil() {
68
			dest.Set(reflect.New(dest.Type().Elem()))
69
		}
70
		return store(dest.Elem(), src)
71
	}
72
	switch src.Kind() {
73
	case reflect.Slice:
74
		return storeSlice(dest, src)
75
	case reflect.Map:
76
		return storeMap(dest, src)
77
	default:
78
		return storeBase(dest, src)
79
	}
80
}
81

82
func storeBase(dest, src reflect.Value) error {
83
	return setDest(dest, src)
84
}
85

86
func setDest(dest, src reflect.Value) error {
87
	if !isVariant(src.Type()) && isVariant(dest.Type()) {
88
		//special conversion for dbus.Variant
89
		dest.Set(reflect.ValueOf(MakeVariant(src.Interface())))
90
		return nil
91
	}
92
	if isVariant(src.Type()) && !isVariant(dest.Type()) {
93
		src = getVariantValue(src)
94
		return store(dest, src)
95
	}
96
	if !src.Type().ConvertibleTo(dest.Type()) {
97
		return fmt.Errorf(
98
			"dbus.Store: type mismatch: cannot convert %s to %s",
99
			src.Type(), dest.Type())
100
	}
101
	dest.Set(src.Convert(dest.Type()))
102
	return nil
103
}
104

105
func kindsAreCompatible(dest, src reflect.Type) bool {
106
	switch {
107
	case isVariant(dest):
108
		return true
109
	case dest.Kind() == reflect.Interface:
110
		return true
111
	default:
112
		return dest.Kind() == src.Kind()
113
	}
114
}
115

116
func isConvertibleTo(dest, src reflect.Type) bool {
117
	switch {
118
	case isVariant(dest):
119
		return true
120
	case dest.Kind() == reflect.Interface:
121
		return true
122
	case dest.Kind() == reflect.Slice:
123
		return src.Kind() == reflect.Slice &&
124
			isConvertibleTo(dest.Elem(), src.Elem())
125
	case dest.Kind() == reflect.Ptr:
126
		dest = dest.Elem()
127
		return isConvertibleTo(dest, src)
128
	case dest.Kind() == reflect.Struct:
129
		return src == interfacesType || dest.Kind() == src.Kind()
130
	default:
131
		return src.ConvertibleTo(dest)
132
	}
133
}
134

135
func storeMap(dest, src reflect.Value) error {
136
	switch {
137
	case !kindsAreCompatible(dest.Type(), src.Type()):
138
		return fmt.Errorf(
139
			"dbus.Store: type mismatch: "+
140
				"map: cannot store a value of %s into %s",
141
			src.Type(), dest.Type())
142
	case isVariant(dest.Type()):
143
		return storeMapIntoVariant(dest, src)
144
	case dest.Kind() == reflect.Interface:
145
		return storeMapIntoInterface(dest, src)
146
	case isConvertibleTo(dest.Type().Key(), src.Type().Key()) &&
147
		isConvertibleTo(dest.Type().Elem(), src.Type().Elem()):
148
		return storeMapIntoMap(dest, src)
149
	default:
150
		return fmt.Errorf(
151
			"dbus.Store: type mismatch: "+
152
				"map: cannot convert a value of %s into %s",
153
			src.Type(), dest.Type())
154
	}
155
}
156

157
func storeMapIntoVariant(dest, src reflect.Value) error {
158
	dv := reflect.MakeMap(src.Type())
159
	err := store(dv, src)
160
	if err != nil {
161
		return err
162
	}
163
	return storeBase(dest, dv)
164
}
165

166
func storeMapIntoInterface(dest, src reflect.Value) error {
167
	var dv reflect.Value
168
	if isVariant(src.Type().Elem()) {
169
		//Convert variants to interface{} recursively when converting
170
		//to interface{}
171
		dv = reflect.MakeMap(
172
			reflect.MapOf(src.Type().Key(), interfaceType))
173
	} else {
174
		dv = reflect.MakeMap(src.Type())
175
	}
176
	err := store(dv, src)
177
	if err != nil {
178
		return err
179
	}
180
	return storeBase(dest, dv)
181
}
182

183
func storeMapIntoMap(dest, src reflect.Value) error {
184
	if dest.IsNil() {
185
		dest.Set(reflect.MakeMap(dest.Type()))
186
	}
187
	keys := src.MapKeys()
188
	for _, key := range keys {
189
		dkey := key.Convert(dest.Type().Key())
190
		dval := reflect.New(dest.Type().Elem()).Elem()
191
		err := store(dval, getVariantValue(src.MapIndex(key)))
192
		if err != nil {
193
			return err
194
		}
195
		dest.SetMapIndex(dkey, dval)
196
	}
197
	return nil
198
}
199

200
func storeSlice(dest, src reflect.Value) error {
201
	switch {
202
	case src.Type() == interfacesType && dest.Kind() == reflect.Struct:
203
		//The decoder always decodes structs as slices of interface{}
204
		return storeStruct(dest, src)
205
	case !kindsAreCompatible(dest.Type(), src.Type()):
206
		return fmt.Errorf(
207
			"dbus.Store: type mismatch: "+
208
				"slice: cannot store a value of %s into %s",
209
			src.Type(), dest.Type())
210
	case isVariant(dest.Type()):
211
		return storeSliceIntoVariant(dest, src)
212
	case dest.Kind() == reflect.Interface:
213
		return storeSliceIntoInterface(dest, src)
214
	case isConvertibleTo(dest.Type().Elem(), src.Type().Elem()):
215
		return storeSliceIntoSlice(dest, src)
216
	default:
217
		return fmt.Errorf(
218
			"dbus.Store: type mismatch: "+
219
				"slice: cannot convert a value of %s into %s",
220
			src.Type(), dest.Type())
221
	}
222
}
223

224
func storeStruct(dest, src reflect.Value) error {
225
	if isVariant(dest.Type()) {
226
		return storeBase(dest, src)
227
	}
228
	dval := make([]interface{}, 0, dest.NumField())
229
	dtype := dest.Type()
230
	for i := 0; i < dest.NumField(); i++ {
231
		field := dest.Field(i)
232
		ftype := dtype.Field(i)
233
		if ftype.PkgPath != "" {
234
			continue
235
		}
236
		if ftype.Tag.Get("dbus") == "-" {
237
			continue
238
		}
239
		dval = append(dval, field.Addr().Interface())
240
	}
241
	if src.Len() != len(dval) {
242
		return fmt.Errorf(
243
			"dbus.Store: type mismatch: "+
244
				"destination struct does not have "+
245
				"enough fields need: %d have: %d",
246
			src.Len(), len(dval))
247
	}
248
	return Store(src.Interface().([]interface{}), dval...)
249
}
250

251
func storeSliceIntoVariant(dest, src reflect.Value) error {
252
	dv := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
253
	err := store(dv, src)
254
	if err != nil {
255
		return err
256
	}
257
	return storeBase(dest, dv)
258
}
259

260
func storeSliceIntoInterface(dest, src reflect.Value) error {
261
	var dv reflect.Value
262
	if isVariant(src.Type().Elem()) {
263
		//Convert variants to interface{} recursively when converting
264
		//to interface{}
265
		dv = reflect.MakeSlice(reflect.SliceOf(interfaceType),
266
			src.Len(), src.Cap())
267
	} else {
268
		dv = reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
269
	}
270
	err := store(dv, src)
271
	if err != nil {
272
		return err
273
	}
274
	return storeBase(dest, dv)
275
}
276

277
func storeSliceIntoSlice(dest, src reflect.Value) error {
278
	if dest.IsNil() || dest.Len() < src.Len() {
279
		dest.Set(reflect.MakeSlice(dest.Type(), src.Len(), src.Cap()))
280
	} else if dest.Len() > src.Len() {
281
		dest.Set(dest.Slice(0, src.Len()))
282
	}
283
	for i := 0; i < src.Len(); i++ {
284
		err := store(dest.Index(i), getVariantValue(src.Index(i)))
285
		if err != nil {
286
			return err
287
		}
288
	}
289
	return nil
290
}
291

292
func getVariantValue(in reflect.Value) reflect.Value {
293
	if isVariant(in.Type()) {
294
		return reflect.ValueOf(in.Interface().(Variant).Value())
295
	}
296
	return in
297
}
298

299
func isVariant(t reflect.Type) bool {
300
	return t == variantType
301
}
302

303
// An ObjectPath is an object path as defined by the D-Bus spec.
304
type ObjectPath string
305

306
// IsValid returns whether the object path is valid.
307
func (o ObjectPath) IsValid() bool {
308
	s := string(o)
309
	if len(s) == 0 {
310
		return false
311
	}
312
	if s[0] != '/' {
313
		return false
314
	}
315
	if s[len(s)-1] == '/' && len(s) != 1 {
316
		return false
317
	}
318
	// probably not used, but technically possible
319
	if s == "/" {
320
		return true
321
	}
322
	split := strings.Split(s[1:], "/")
323
	for _, v := range split {
324
		if len(v) == 0 {
325
			return false
326
		}
327
		for _, c := range v {
328
			if !isMemberChar(c) {
329
				return false
330
			}
331
		}
332
	}
333
	return true
334
}
335

336
// A UnixFD is a Unix file descriptor sent over the wire. See the package-level
337
// documentation for more information about Unix file descriptor passsing.
338
type UnixFD int32
339

340
// A UnixFDIndex is the representation of a Unix file descriptor in a message.
341
type UnixFDIndex uint32
342

343
// alignment returns the alignment of values of type t.
344
func alignment(t reflect.Type) int {
345
	switch t {
346
	case variantType:
347
		return 1
348
	case objectPathType:
349
		return 4
350
	case signatureType:
351
		return 1
352
	case interfacesType:
353
		return 4
354
	}
355
	switch t.Kind() {
356
	case reflect.Uint8:
357
		return 1
358
	case reflect.Uint16, reflect.Int16:
359
		return 2
360
	case reflect.Uint, reflect.Int, reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map:
361
		return 4
362
	case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct:
363
		return 8
364
	case reflect.Ptr:
365
		return alignment(t.Elem())
366
	}
367
	return 1
368
}
369

370
// isKeyType returns whether t is a valid type for a D-Bus dict.
371
func isKeyType(t reflect.Type) bool {
372
	switch t.Kind() {
373
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
374
		reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64,
375
		reflect.String, reflect.Uint, reflect.Int:
376

377
		return true
378
	}
379
	return false
380
}
381

382
// isValidInterface returns whether s is a valid name for an interface.
383
func isValidInterface(s string) bool {
384
	if len(s) == 0 || len(s) > 255 || s[0] == '.' {
385
		return false
386
	}
387
	elem := strings.Split(s, ".")
388
	if len(elem) < 2 {
389
		return false
390
	}
391
	for _, v := range elem {
392
		if len(v) == 0 {
393
			return false
394
		}
395
		if v[0] >= '0' && v[0] <= '9' {
396
			return false
397
		}
398
		for _, c := range v {
399
			if !isMemberChar(c) {
400
				return false
401
			}
402
		}
403
	}
404
	return true
405
}
406

407
// isValidMember returns whether s is a valid name for a member.
408
func isValidMember(s string) bool {
409
	if len(s) == 0 || len(s) > 255 {
410
		return false
411
	}
412
	i := strings.Index(s, ".")
413
	if i != -1 {
414
		return false
415
	}
416
	if s[0] >= '0' && s[0] <= '9' {
417
		return false
418
	}
419
	for _, c := range s {
420
		if !isMemberChar(c) {
421
			return false
422
		}
423
	}
424
	return true
425
}
426

427
func isMemberChar(c rune) bool {
428
	return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
429
		(c >= 'a' && c <= 'z') || c == '_'
430
}
431

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

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

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

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