summaryrefslogtreecommitdiff
path: root/vendor/github.com/godbus/dbus/decoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/godbus/dbus/decoder.go')
-rw-r--r--vendor/github.com/godbus/dbus/decoder.go53
1 files changed, 52 insertions, 1 deletions
diff --git a/vendor/github.com/godbus/dbus/decoder.go b/vendor/github.com/godbus/dbus/decoder.go
index 5c27d3b51..ede91575b 100644
--- a/vendor/github.com/godbus/dbus/decoder.go
+++ b/vendor/github.com/godbus/dbus/decoder.go
@@ -188,8 +188,14 @@ func (dec *decoder) decode(s string, depth int) interface{} {
if depth >= 64 {
panic(FormatError("input exceeds container depth limit"))
}
+ sig := s[1:]
length := dec.decode("u", depth).(uint32)
- v := reflect.MakeSlice(reflect.SliceOf(typeFor(s[1:])), 0, int(length))
+ // capacity can be determined only for fixed-size element types
+ var capacity int
+ if s := sigByteSize(sig); s != 0 {
+ capacity = int(length) / s
+ }
+ v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity)
// Even for empty arrays, the correct padding must be included
align := alignment(typeFor(s[1:]))
if len(s) > 1 && s[1] == '(' {
@@ -227,6 +233,51 @@ func (dec *decoder) decode(s string, depth int) interface{} {
}
}
+// sigByteSize tries to calculates size of the given signature in bytes.
+//
+// It returns zero when it can't, for example when it contains non-fixed size
+// types such as strings, maps and arrays that require reading of the transmitted
+// data, for that we would need to implement the unread method for Decoder first.
+func sigByteSize(sig string) int {
+ var total int
+ for offset := 0; offset < len(sig); {
+ switch sig[offset] {
+ case 'y':
+ total += 1
+ offset += 1
+ case 'n', 'q':
+ total += 2
+ offset += 1
+ case 'b', 'i', 'u', 'h':
+ total += 4
+ offset += 1
+ case 'x', 't', 'd':
+ total += 8
+ offset += 1
+ case '(':
+ i := 1
+ depth := 1
+ for i < len(sig[offset:]) && depth != 0 {
+ if sig[offset+i] == '(' {
+ depth++
+ } else if sig[offset+i] == ')' {
+ depth--
+ }
+ i++
+ }
+ s := sigByteSize(sig[offset+1 : offset+i-1])
+ if s == 0 {
+ return 0
+ }
+ total += s
+ offset += i
+ default:
+ return 0
+ }
+ }
+ return total
+}
+
// A FormatError is an error in the wire format.
type FormatError string