1 package dbus
2
3 import (
4 "bytes"
5 "fmt"
6 "reflect"
7 "sort"
8 "strconv"
9 )
10
11
12 type Variant struct {
13 sig Signature
14 value interface{}
15 }
16
17
18
19 func MakeVariant(v interface{}) Variant {
20 return MakeVariantWithSignature(v, SignatureOf(v))
21 }
22
23
24 func MakeVariantWithSignature(v interface{}, s Signature) Variant {
25 return Variant{s, v}
26 }
27
28
29
30
31 func ParseVariant(s string, sig Signature) (Variant, error) {
32 tokens := varLex(s)
33 p := &varParser{tokens: tokens}
34 n, err := varMakeNode(p)
35 if err != nil {
36 return Variant{}, err
37 }
38 if sig.str == "" {
39 sig, err = varInfer(n)
40 if err != nil {
41 return Variant{}, err
42 }
43 }
44 v, err := n.Value(sig)
45 if err != nil {
46 return Variant{}, err
47 }
48 return MakeVariant(v), nil
49 }
50
51
52
53 func (v Variant) format() (string, bool) {
54 switch v.sig.str[0] {
55 case 'b', 'i':
56 return fmt.Sprint(v.value), true
57 case 'n', 'q', 'u', 'x', 't', 'd', 'h':
58 return fmt.Sprint(v.value), false
59 case 's':
60 return strconv.Quote(v.value.(string)), true
61 case 'o':
62 return strconv.Quote(string(v.value.(ObjectPath))), false
63 case 'g':
64 return strconv.Quote(v.value.(Signature).str), false
65 case 'v':
66 s, unamb := v.value.(Variant).format()
67 if !unamb {
68 return "<@" + v.value.(Variant).sig.str + " " + s + ">", true
69 }
70 return "<" + s + ">", true
71 case 'y':
72 return fmt.Sprintf("%#x", v.value.(byte)), false
73 }
74 rv := reflect.ValueOf(v.value)
75 switch rv.Kind() {
76 case reflect.Slice:
77 if rv.Len() == 0 {
78 return "[]", false
79 }
80 unamb := true
81 buf := bytes.NewBuffer([]byte("["))
82 for i := 0; i < rv.Len(); i++ {
83
84 s, b := MakeVariant(rv.Index(i).Interface()).format()
85 unamb = unamb && b
86 buf.WriteString(s)
87 if i != rv.Len()-1 {
88 buf.WriteString(", ")
89 }
90 }
91 buf.WriteByte(']')
92 return buf.String(), unamb
93 case reflect.Map:
94 if rv.Len() == 0 {
95 return "{}", false
96 }
97 unamb := true
98 var buf bytes.Buffer
99 kvs := make([]string, rv.Len())
100 for i, k := range rv.MapKeys() {
101 s, b := MakeVariant(k.Interface()).format()
102 unamb = unamb && b
103 buf.Reset()
104 buf.WriteString(s)
105 buf.WriteString(": ")
106 s, b = MakeVariant(rv.MapIndex(k).Interface()).format()
107 unamb = unamb && b
108 buf.WriteString(s)
109 kvs[i] = buf.String()
110 }
111 buf.Reset()
112 buf.WriteByte('{')
113 sort.Strings(kvs)
114 for i, kv := range kvs {
115 if i > 0 {
116 buf.WriteString(", ")
117 }
118 buf.WriteString(kv)
119 }
120 buf.WriteByte('}')
121 return buf.String(), unamb
122 }
123 return `"INVALID"`, true
124 }
125
126
127 func (v Variant) Signature() Signature {
128 return v.sig
129 }
130
131
132
133 func (v Variant) String() string {
134 s, unamb := v.format()
135 if !unamb {
136 return "@" + v.sig.str + " " + s
137 }
138 return s
139 }
140
141
142 func (v Variant) Value() interface{} {
143 return v.value
144 }
145
146
147
148 func (v Variant) Store(value interface{}) error {
149 return storeInterfaces(v.value, value)
150 }
151
View as plain text