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
35
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
45
46
47
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
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
170
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
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
264
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
304 type ObjectPath string
305
306
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
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
337
338 type UnixFD int32
339
340
341 type UnixFDIndex uint32
342
343
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
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
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
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
View as plain text