1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
package dbus
import (
"errors"
"fmt"
"reflect"
)
var (
typeObjectPather = reflect.TypeOf((*ObjectPather)(nil)).Elem()
typeVariant = reflect.TypeOf(Variant{})
typeSignature = reflect.TypeOf(Signature(""))
typeBlankInterface = reflect.TypeOf((*interface{})(nil)).Elem()
)
type Signature string
func SignatureOf(t reflect.Type) (Signature, error) {
if t.AssignableTo(typeObjectPather) {
return Signature("o"), nil
}
switch t.Kind() {
case reflect.Uint8:
return Signature("y"), nil
case reflect.Bool:
return Signature("b"), nil
case reflect.Int16:
return Signature("n"), nil
case reflect.Uint16:
return Signature("q"), nil
case reflect.Int32:
return Signature("i"), nil
case reflect.Uint32:
return Signature("u"), nil
case reflect.Int64:
return Signature("x"), nil
case reflect.Uint64:
return Signature("t"), nil
case reflect.Float64:
return Signature("d"), nil
case reflect.String:
if t == typeSignature {
return Signature("g"), nil
}
return Signature("s"), nil
case reflect.Array, reflect.Slice:
valueSig, err := SignatureOf(t.Elem())
if err != nil {
return Signature(""), err
}
return Signature("a") + valueSig, nil
case reflect.Map:
keySig, err := SignatureOf(t.Key())
if err != nil {
return Signature(""), err
}
valueSig, err := SignatureOf(t.Elem())
if err != nil {
return Signature(""), err
}
return Signature("a{") + keySig + valueSig + Signature("}"), nil
case reflect.Struct:
// Special case the variant structure
if t == typeVariant {
return Signature("v"), nil
}
sig := Signature("(")
for i := 0; i != t.NumField(); i++ {
fieldSig, err := SignatureOf(t.Field(i).Type)
if err != nil {
return Signature(""), err
}
sig += fieldSig
}
sig += Signature(")")
return sig, nil
case reflect.Ptr:
// dereference pointers
sig, err := SignatureOf(t.Elem())
return sig, err
}
return Signature(""), errors.New("Can not determine signature for " + t.String())
}
func (sig Signature) NextType(offset int) (next int, err error) {
if offset >= len(sig) {
err = errors.New("No more types codes in signature")
return
}
switch sig[offset] {
case 'y', 'b', 'n', 'q', 'i', 'u', 'x', 't', 'd', 's', 'o', 'g', 'v', 'h':
// A basic type code.
next = offset + 1
case 'a':
// An array: consume the embedded type code
next, err = sig.NextType(offset + 1)
case '{':
// A pair used in maps: consume the two contained types
next, err = sig.NextType(offset + 1)
if err != nil {
return
}
next, err = sig.NextType(next)
if err != nil {
return
}
if next >= len(sig) || sig[next] != '}' {
err = errors.New("Pair does not end with '}'")
return
}
next += 1
case '(':
// A struct: consume types until we
next = offset + 1
for {
if next < len(sig) && sig[next] == ')' {
next += 1
return
}
next, err = sig.NextType(next)
if err != nil {
return
}
}
default:
err = errors.New("Unknown type code " + string(sig[offset]))
}
return
}
// Validate that the signature is a valid string of type codes
func (sig Signature) Validate() (err error) {
offset := 0
for offset < len(sig) {
offset, err = sig.NextType(offset)
if err != nil {
break
}
}
return
}
type ObjectPath string
type ObjectPather interface {
ObjectPath() ObjectPath
}
func (o ObjectPath) ObjectPath() ObjectPath {
return o
}
type Variant struct {
Value interface{}
}
func (v *Variant) GetVariantSignature() (Signature, error) {
return SignatureOf(reflect.TypeOf(v.Value))
}
type Error struct {
Name string
Message string
}
func (e *Error) Error() string {
return fmt.Sprint(e.Name, ": ", e.Message)
}
|