dbus.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package dbus
  2. import (
  3. "errors"
  4. "reflect"
  5. "strings"
  6. )
  7. var (
  8. byteType = reflect.TypeOf(byte(0))
  9. boolType = reflect.TypeOf(false)
  10. uint8Type = reflect.TypeOf(uint8(0))
  11. int16Type = reflect.TypeOf(int16(0))
  12. uint16Type = reflect.TypeOf(uint16(0))
  13. int32Type = reflect.TypeOf(int32(0))
  14. uint32Type = reflect.TypeOf(uint32(0))
  15. int64Type = reflect.TypeOf(int64(0))
  16. uint64Type = reflect.TypeOf(uint64(0))
  17. float64Type = reflect.TypeOf(float64(0))
  18. stringType = reflect.TypeOf("")
  19. signatureType = reflect.TypeOf(Signature{""})
  20. objectPathType = reflect.TypeOf(ObjectPath(""))
  21. variantType = reflect.TypeOf(Variant{Signature{""}, nil})
  22. interfacesType = reflect.TypeOf([]interface{}{})
  23. unixFDType = reflect.TypeOf(UnixFD(0))
  24. unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
  25. )
  26. // An InvalidTypeError signals that a value which cannot be represented in the
  27. // D-Bus wire format was passed to a function.
  28. type InvalidTypeError struct {
  29. Type reflect.Type
  30. }
  31. func (e InvalidTypeError) Error() string {
  32. return "dbus: invalid type " + e.Type.String()
  33. }
  34. // Store copies the values contained in src to dest, which must be a slice of
  35. // pointers. It converts slices of interfaces from src to corresponding structs
  36. // in dest. An error is returned if the lengths of src and dest or the types of
  37. // their elements don't match.
  38. func Store(src []interface{}, dest ...interface{}) error {
  39. if len(src) != len(dest) {
  40. return errors.New("dbus.Store: length mismatch")
  41. }
  42. for i := range src {
  43. if err := store(src[i], dest[i]); err != nil {
  44. return err
  45. }
  46. }
  47. return nil
  48. }
  49. func store(src, dest interface{}) error {
  50. if reflect.TypeOf(dest).Elem() == reflect.TypeOf(src) {
  51. reflect.ValueOf(dest).Elem().Set(reflect.ValueOf(src))
  52. return nil
  53. } else if hasStruct(dest) {
  54. rv := reflect.ValueOf(dest).Elem()
  55. switch rv.Kind() {
  56. case reflect.Struct:
  57. vs, ok := src.([]interface{})
  58. if !ok {
  59. return errors.New("dbus.Store: type mismatch")
  60. }
  61. t := rv.Type()
  62. ndest := make([]interface{}, 0, rv.NumField())
  63. for i := 0; i < rv.NumField(); i++ {
  64. field := t.Field(i)
  65. if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
  66. ndest = append(ndest, rv.Field(i).Addr().Interface())
  67. }
  68. }
  69. if len(vs) != len(ndest) {
  70. return errors.New("dbus.Store: type mismatch")
  71. }
  72. err := Store(vs, ndest...)
  73. if err != nil {
  74. return errors.New("dbus.Store: type mismatch")
  75. }
  76. case reflect.Slice:
  77. sv := reflect.ValueOf(src)
  78. if sv.Kind() != reflect.Slice {
  79. return errors.New("dbus.Store: type mismatch")
  80. }
  81. rv.Set(reflect.MakeSlice(rv.Type(), sv.Len(), sv.Len()))
  82. for i := 0; i < sv.Len(); i++ {
  83. if err := store(sv.Index(i).Interface(), rv.Index(i).Addr().Interface()); err != nil {
  84. return err
  85. }
  86. }
  87. case reflect.Map:
  88. sv := reflect.ValueOf(src)
  89. if sv.Kind() != reflect.Map {
  90. return errors.New("dbus.Store: type mismatch")
  91. }
  92. keys := sv.MapKeys()
  93. rv.Set(reflect.MakeMap(sv.Type()))
  94. for _, key := range keys {
  95. v := reflect.New(sv.Type().Elem())
  96. if err := store(v, sv.MapIndex(key).Interface()); err != nil {
  97. return err
  98. }
  99. rv.SetMapIndex(key, v.Elem())
  100. }
  101. default:
  102. return errors.New("dbus.Store: type mismatch")
  103. }
  104. return nil
  105. } else {
  106. return errors.New("dbus.Store: type mismatch")
  107. }
  108. }
  109. func hasStruct(v interface{}) bool {
  110. t := reflect.TypeOf(v)
  111. for {
  112. switch t.Kind() {
  113. case reflect.Struct:
  114. return true
  115. case reflect.Slice, reflect.Ptr, reflect.Map:
  116. t = t.Elem()
  117. default:
  118. return false
  119. }
  120. }
  121. }
  122. // An ObjectPath is an object path as defined by the D-Bus spec.
  123. type ObjectPath string
  124. // IsValid returns whether the object path is valid.
  125. func (o ObjectPath) IsValid() bool {
  126. s := string(o)
  127. if len(s) == 0 {
  128. return false
  129. }
  130. if s[0] != '/' {
  131. return false
  132. }
  133. if s[len(s)-1] == '/' && len(s) != 1 {
  134. return false
  135. }
  136. // probably not used, but technically possible
  137. if s == "/" {
  138. return true
  139. }
  140. split := strings.Split(s[1:], "/")
  141. for _, v := range split {
  142. if len(v) == 0 {
  143. return false
  144. }
  145. for _, c := range v {
  146. if !isMemberChar(c) {
  147. return false
  148. }
  149. }
  150. }
  151. return true
  152. }
  153. // A UnixFD is a Unix file descriptor sent over the wire. See the package-level
  154. // documentation for more information about Unix file descriptor passsing.
  155. type UnixFD int32
  156. // A UnixFDIndex is the representation of a Unix file descriptor in a message.
  157. type UnixFDIndex uint32
  158. // alignment returns the alignment of values of type t.
  159. func alignment(t reflect.Type) int {
  160. switch t {
  161. case variantType:
  162. return 1
  163. case objectPathType:
  164. return 4
  165. case signatureType:
  166. return 1
  167. case interfacesType: // sometimes used for structs
  168. return 8
  169. }
  170. switch t.Kind() {
  171. case reflect.Uint8:
  172. return 1
  173. case reflect.Uint16, reflect.Int16:
  174. return 2
  175. case reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map:
  176. return 4
  177. case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct:
  178. return 8
  179. case reflect.Ptr:
  180. return alignment(t.Elem())
  181. }
  182. return 1
  183. }
  184. // isKeyType returns whether t is a valid type for a D-Bus dict.
  185. func isKeyType(t reflect.Type) bool {
  186. switch t.Kind() {
  187. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  188. reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64,
  189. reflect.String:
  190. return true
  191. }
  192. return false
  193. }
  194. // isValidInterface returns whether s is a valid name for an interface.
  195. func isValidInterface(s string) bool {
  196. if len(s) == 0 || len(s) > 255 || s[0] == '.' {
  197. return false
  198. }
  199. elem := strings.Split(s, ".")
  200. if len(elem) < 2 {
  201. return false
  202. }
  203. for _, v := range elem {
  204. if len(v) == 0 {
  205. return false
  206. }
  207. if v[0] >= '0' && v[0] <= '9' {
  208. return false
  209. }
  210. for _, c := range v {
  211. if !isMemberChar(c) {
  212. return false
  213. }
  214. }
  215. }
  216. return true
  217. }
  218. // isValidMember returns whether s is a valid name for a member.
  219. func isValidMember(s string) bool {
  220. if len(s) == 0 || len(s) > 255 {
  221. return false
  222. }
  223. i := strings.Index(s, ".")
  224. if i != -1 {
  225. return false
  226. }
  227. if s[0] >= '0' && s[0] <= '9' {
  228. return false
  229. }
  230. for _, c := range s {
  231. if !isMemberChar(c) {
  232. return false
  233. }
  234. }
  235. return true
  236. }
  237. func isMemberChar(c rune) bool {
  238. return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
  239. (c >= 'a' && c <= 'z') || c == '_'
  240. }