go-tg-screenshot-bot

Форк
0
150 строк · 3.6 Кб
1
package dbus
2

3
import (
4
	"bytes"
5
	"fmt"
6
	"reflect"
7
	"sort"
8
	"strconv"
9
)
10

11
// Variant represents the D-Bus variant type.
12
type Variant struct {
13
	sig   Signature
14
	value interface{}
15
}
16

17
// MakeVariant converts the given value to a Variant. It panics if v cannot be
18
// represented as a D-Bus type.
19
func MakeVariant(v interface{}) Variant {
20
	return MakeVariantWithSignature(v, SignatureOf(v))
21
}
22

23
// MakeVariantWithSignature converts the given value to a Variant.
24
func MakeVariantWithSignature(v interface{}, s Signature) Variant {
25
	return Variant{s, v}
26
}
27

28
// ParseVariant parses the given string as a variant as described at
29
// https://developer.gnome.org/glib/stable/gvariant-text.html. If sig is not
30
// empty, it is taken to be the expected signature for the variant.
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
// format returns a formatted version of v and whether this string can be parsed
52
// unambiguously.
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
			// TODO: slooow
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
// Signature returns the D-Bus signature of the underlying value of v.
127
func (v Variant) Signature() Signature {
128
	return v.sig
129
}
130

131
// String returns the string representation of the underlying value of v as
132
// described at https://developer.gnome.org/glib/stable/gvariant-text.html.
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
// Value returns the underlying value of v.
142
func (v Variant) Value() interface{} {
143
	return v.value
144
}
145

146
// Store converts the variant into a native go type using the same
147
// mechanism as the "Store" function.
148
func (v Variant) Store(value interface{}) error {
149
	return storeInterfaces(v.value, value)
150
}
151

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.