introspectable.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package introspect
  2. import (
  3. "encoding/xml"
  4. "reflect"
  5. "strings"
  6. "github.com/godbus/dbus/v5"
  7. )
  8. // Introspectable implements org.freedesktop.Introspectable.
  9. //
  10. // You can create it by converting the XML-formatted introspection data from a
  11. // string to an Introspectable or call NewIntrospectable with a Node. Then,
  12. // export it as org.freedesktop.Introspectable on you object.
  13. type Introspectable string
  14. // NewIntrospectable returns an Introspectable that returns the introspection
  15. // data that corresponds to the given Node. If n.Interfaces doesn't contain the
  16. // data for org.freedesktop.DBus.Introspectable, it is added automatically.
  17. func NewIntrospectable(n *Node) Introspectable {
  18. found := false
  19. for _, v := range n.Interfaces {
  20. if v.Name == "org.freedesktop.DBus.Introspectable" {
  21. found = true
  22. break
  23. }
  24. }
  25. if !found {
  26. n.Interfaces = append(n.Interfaces, IntrospectData)
  27. }
  28. b, err := xml.Marshal(n)
  29. if err != nil {
  30. panic(err)
  31. }
  32. return Introspectable(strings.TrimSpace(IntrospectDeclarationString) + string(b))
  33. }
  34. // Introspect implements org.freedesktop.Introspectable.Introspect.
  35. func (i Introspectable) Introspect() (string, *dbus.Error) {
  36. return string(i), nil
  37. }
  38. // Methods returns the description of the methods of v. This can be used to
  39. // create a Node which can be passed to NewIntrospectable.
  40. func Methods(v interface{}) []Method {
  41. t := reflect.TypeOf(v)
  42. ms := make([]Method, 0, t.NumMethod())
  43. for i := 0; i < t.NumMethod(); i++ {
  44. if t.Method(i).PkgPath != "" {
  45. continue
  46. }
  47. mt := t.Method(i).Type
  48. if mt.NumOut() == 0 ||
  49. mt.Out(mt.NumOut()-1) != reflect.TypeOf(&dbus.Error{}) {
  50. continue
  51. }
  52. var m Method
  53. m.Name = t.Method(i).Name
  54. m.Args = make([]Arg, 0, mt.NumIn()+mt.NumOut()-2)
  55. for j := 1; j < mt.NumIn(); j++ {
  56. if mt.In(j) != reflect.TypeOf((*dbus.Sender)(nil)).Elem() &&
  57. mt.In(j) != reflect.TypeOf((*dbus.Message)(nil)).Elem() {
  58. arg := Arg{"", dbus.SignatureOfType(mt.In(j)).String(), "in"}
  59. m.Args = append(m.Args, arg)
  60. }
  61. }
  62. for j := 0; j < mt.NumOut()-1; j++ {
  63. arg := Arg{"", dbus.SignatureOfType(mt.Out(j)).String(), "out"}
  64. m.Args = append(m.Args, arg)
  65. }
  66. m.Annotations = make([]Annotation, 0)
  67. ms = append(ms, m)
  68. }
  69. return ms
  70. }