dbus.go (10847B)
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.Struct: 126 return src == interfacesType 127 default: 128 return src.ConvertibleTo(dest) 129 } 130 } 131 132 func storeMap(dest, src reflect.Value) error { 133 switch { 134 case !kindsAreCompatible(dest.Type(), src.Type()): 135 return fmt.Errorf( 136 "dbus.Store: type mismatch: "+ 137 "map: cannot store a value of %s into %s", 138 src.Type(), dest.Type()) 139 case isVariant(dest.Type()): 140 return storeMapIntoVariant(dest, src) 141 case dest.Kind() == reflect.Interface: 142 return storeMapIntoInterface(dest, src) 143 case isConvertibleTo(dest.Type().Key(), src.Type().Key()) && 144 isConvertibleTo(dest.Type().Elem(), src.Type().Elem()): 145 return storeMapIntoMap(dest, src) 146 default: 147 return fmt.Errorf( 148 "dbus.Store: type mismatch: "+ 149 "map: cannot convert a value of %s into %s", 150 src.Type(), dest.Type()) 151 } 152 } 153 154 func storeMapIntoVariant(dest, src reflect.Value) error { 155 dv := reflect.MakeMap(src.Type()) 156 err := store(dv, src) 157 if err != nil { 158 return err 159 } 160 return storeBase(dest, dv) 161 } 162 163 func storeMapIntoInterface(dest, src reflect.Value) error { 164 var dv reflect.Value 165 if isVariant(src.Type().Elem()) { 166 //Convert variants to interface{} recursively when converting 167 //to interface{} 168 dv = reflect.MakeMap( 169 reflect.MapOf(src.Type().Key(), interfaceType)) 170 } else { 171 dv = reflect.MakeMap(src.Type()) 172 } 173 err := store(dv, src) 174 if err != nil { 175 return err 176 } 177 return storeBase(dest, dv) 178 } 179 180 func storeMapIntoMap(dest, src reflect.Value) error { 181 if dest.IsNil() { 182 dest.Set(reflect.MakeMap(dest.Type())) 183 } 184 keys := src.MapKeys() 185 for _, key := range keys { 186 dkey := key.Convert(dest.Type().Key()) 187 dval := reflect.New(dest.Type().Elem()).Elem() 188 err := store(dval, getVariantValue(src.MapIndex(key))) 189 if err != nil { 190 return err 191 } 192 dest.SetMapIndex(dkey, dval) 193 } 194 return nil 195 } 196 197 func storeSlice(dest, src reflect.Value) error { 198 switch { 199 case src.Type() == interfacesType && dest.Kind() == reflect.Struct: 200 //The decoder always decodes structs as slices of interface{} 201 return storeStruct(dest, src) 202 case !kindsAreCompatible(dest.Type(), src.Type()): 203 return fmt.Errorf( 204 "dbus.Store: type mismatch: "+ 205 "slice: cannot store a value of %s into %s", 206 src.Type(), dest.Type()) 207 case isVariant(dest.Type()): 208 return storeSliceIntoVariant(dest, src) 209 case dest.Kind() == reflect.Interface: 210 return storeSliceIntoInterface(dest, src) 211 case isConvertibleTo(dest.Type().Elem(), src.Type().Elem()): 212 return storeSliceIntoSlice(dest, src) 213 default: 214 return fmt.Errorf( 215 "dbus.Store: type mismatch: "+ 216 "slice: cannot convert a value of %s into %s", 217 src.Type(), dest.Type()) 218 } 219 } 220 221 func storeStruct(dest, src reflect.Value) error { 222 if isVariant(dest.Type()) { 223 return storeBase(dest, src) 224 } 225 dval := make([]interface{}, 0, dest.NumField()) 226 dtype := dest.Type() 227 for i := 0; i < dest.NumField(); i++ { 228 field := dest.Field(i) 229 ftype := dtype.Field(i) 230 if ftype.PkgPath != "" { 231 continue 232 } 233 if ftype.Tag.Get("dbus") == "-" { 234 continue 235 } 236 dval = append(dval, field.Addr().Interface()) 237 } 238 if src.Len() != len(dval) { 239 return fmt.Errorf( 240 "dbus.Store: type mismatch: "+ 241 "destination struct does not have "+ 242 "enough fields need: %d have: %d", 243 src.Len(), len(dval)) 244 } 245 return Store(src.Interface().([]interface{}), dval...) 246 } 247 248 func storeSliceIntoVariant(dest, src reflect.Value) error { 249 dv := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) 250 err := store(dv, src) 251 if err != nil { 252 return err 253 } 254 return storeBase(dest, dv) 255 } 256 257 func storeSliceIntoInterface(dest, src reflect.Value) error { 258 var dv reflect.Value 259 if isVariant(src.Type().Elem()) { 260 //Convert variants to interface{} recursively when converting 261 //to interface{} 262 dv = reflect.MakeSlice(reflect.SliceOf(interfaceType), 263 src.Len(), src.Cap()) 264 } else { 265 dv = reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) 266 } 267 err := store(dv, src) 268 if err != nil { 269 return err 270 } 271 return storeBase(dest, dv) 272 } 273 274 func storeSliceIntoSlice(dest, src reflect.Value) error { 275 if dest.IsNil() || dest.Len() < src.Len() { 276 dest.Set(reflect.MakeSlice(dest.Type(), src.Len(), src.Cap())) 277 } 278 if dest.Len() != src.Len() { 279 return fmt.Errorf( 280 "dbus.Store: type mismatch: "+ 281 "slices are different lengths "+ 282 "need: %d have: %d", 283 src.Len(), dest.Len()) 284 } 285 for i := 0; i < src.Len(); i++ { 286 err := store(dest.Index(i), getVariantValue(src.Index(i))) 287 if err != nil { 288 return err 289 } 290 } 291 return nil 292 } 293 294 func getVariantValue(in reflect.Value) reflect.Value { 295 if isVariant(in.Type()) { 296 return reflect.ValueOf(in.Interface().(Variant).Value()) 297 } 298 return in 299 } 300 301 func isVariant(t reflect.Type) bool { 302 return t == variantType 303 } 304 305 // An ObjectPath is an object path as defined by the D-Bus spec. 306 type ObjectPath string 307 308 // IsValid returns whether the object path is valid. 309 func (o ObjectPath) IsValid() bool { 310 s := string(o) 311 if len(s) == 0 { 312 return false 313 } 314 if s[0] != '/' { 315 return false 316 } 317 if s[len(s)-1] == '/' && len(s) != 1 { 318 return false 319 } 320 // probably not used, but technically possible 321 if s == "/" { 322 return true 323 } 324 split := strings.Split(s[1:], "/") 325 for _, v := range split { 326 if len(v) == 0 { 327 return false 328 } 329 for _, c := range v { 330 if !isMemberChar(c) { 331 return false 332 } 333 } 334 } 335 return true 336 } 337 338 // A UnixFD is a Unix file descriptor sent over the wire. See the package-level 339 // documentation for more information about Unix file descriptor passsing. 340 type UnixFD int32 341 342 // A UnixFDIndex is the representation of a Unix file descriptor in a message. 343 type UnixFDIndex uint32 344 345 // alignment returns the alignment of values of type t. 346 func alignment(t reflect.Type) int { 347 switch t { 348 case variantType: 349 return 1 350 case objectPathType: 351 return 4 352 case signatureType: 353 return 1 354 case interfacesType: 355 return 4 356 } 357 switch t.Kind() { 358 case reflect.Uint8: 359 return 1 360 case reflect.Uint16, reflect.Int16: 361 return 2 362 case reflect.Uint, reflect.Int, reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map: 363 return 4 364 case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct: 365 return 8 366 case reflect.Ptr: 367 return alignment(t.Elem()) 368 } 369 return 1 370 } 371 372 // isKeyType returns whether t is a valid type for a D-Bus dict. 373 func isKeyType(t reflect.Type) bool { 374 switch t.Kind() { 375 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 376 reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, 377 reflect.String, reflect.Uint, reflect.Int: 378 379 return true 380 } 381 return false 382 } 383 384 // isValidInterface returns whether s is a valid name for an interface. 385 func isValidInterface(s string) bool { 386 if len(s) == 0 || len(s) > 255 || s[0] == '.' { 387 return false 388 } 389 elem := strings.Split(s, ".") 390 if len(elem) < 2 { 391 return false 392 } 393 for _, v := range elem { 394 if len(v) == 0 { 395 return false 396 } 397 if v[0] >= '0' && v[0] <= '9' { 398 return false 399 } 400 for _, c := range v { 401 if !isMemberChar(c) { 402 return false 403 } 404 } 405 } 406 return true 407 } 408 409 // isValidMember returns whether s is a valid name for a member. 410 func isValidMember(s string) bool { 411 if len(s) == 0 || len(s) > 255 { 412 return false 413 } 414 i := strings.Index(s, ".") 415 if i != -1 { 416 return false 417 } 418 if s[0] >= '0' && s[0] <= '9' { 419 return false 420 } 421 for _, c := range s { 422 if !isMemberChar(c) { 423 return false 424 } 425 } 426 return true 427 } 428 429 func isMemberChar(c rune) bool { 430 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || 431 (c >= 'a' && c <= 'z') || c == '_' 432 }