prometheusmetricshost-metricsmachine-metricsnode-metricsprocfsprometheus-exportersystem-informationsystem-metrics
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
5.0 KiB
228 lines
5.0 KiB
package dbus |
|
|
|
import ( |
|
"encoding/binary" |
|
"io" |
|
"reflect" |
|
) |
|
|
|
type decoder struct { |
|
in io.Reader |
|
order binary.ByteOrder |
|
pos int |
|
} |
|
|
|
// newDecoder returns a new decoder that reads values from in. The input is |
|
// expected to be in the given byte order. |
|
func newDecoder(in io.Reader, order binary.ByteOrder) *decoder { |
|
dec := new(decoder) |
|
dec.in = in |
|
dec.order = order |
|
return dec |
|
} |
|
|
|
// align aligns the input to the given boundary and panics on error. |
|
func (dec *decoder) align(n int) { |
|
if dec.pos%n != 0 { |
|
newpos := (dec.pos + n - 1) & ^(n - 1) |
|
empty := make([]byte, newpos-dec.pos) |
|
if _, err := io.ReadFull(dec.in, empty); err != nil { |
|
panic(err) |
|
} |
|
dec.pos = newpos |
|
} |
|
} |
|
|
|
// Calls binary.Read(dec.in, dec.order, v) and panics on read errors. |
|
func (dec *decoder) binread(v interface{}) { |
|
if err := binary.Read(dec.in, dec.order, v); err != nil { |
|
panic(err) |
|
} |
|
} |
|
|
|
func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) { |
|
defer func() { |
|
var ok bool |
|
v := recover() |
|
if err, ok = v.(error); ok { |
|
if err == io.EOF || err == io.ErrUnexpectedEOF { |
|
err = FormatError("unexpected EOF") |
|
} |
|
} |
|
}() |
|
vs = make([]interface{}, 0) |
|
s := sig.str |
|
for s != "" { |
|
err, rem := validSingle(s, 0) |
|
if err != nil { |
|
return nil, err |
|
} |
|
v := dec.decode(s[:len(s)-len(rem)], 0) |
|
vs = append(vs, v) |
|
s = rem |
|
} |
|
return vs, nil |
|
} |
|
|
|
func (dec *decoder) decode(s string, depth int) interface{} { |
|
dec.align(alignment(typeFor(s))) |
|
switch s[0] { |
|
case 'y': |
|
var b [1]byte |
|
if _, err := dec.in.Read(b[:]); err != nil { |
|
panic(err) |
|
} |
|
dec.pos++ |
|
return b[0] |
|
case 'b': |
|
i := dec.decode("u", depth).(uint32) |
|
switch { |
|
case i == 0: |
|
return false |
|
case i == 1: |
|
return true |
|
default: |
|
panic(FormatError("invalid value for boolean")) |
|
} |
|
case 'n': |
|
var i int16 |
|
dec.binread(&i) |
|
dec.pos += 2 |
|
return i |
|
case 'i': |
|
var i int32 |
|
dec.binread(&i) |
|
dec.pos += 4 |
|
return i |
|
case 'x': |
|
var i int64 |
|
dec.binread(&i) |
|
dec.pos += 8 |
|
return i |
|
case 'q': |
|
var i uint16 |
|
dec.binread(&i) |
|
dec.pos += 2 |
|
return i |
|
case 'u': |
|
var i uint32 |
|
dec.binread(&i) |
|
dec.pos += 4 |
|
return i |
|
case 't': |
|
var i uint64 |
|
dec.binread(&i) |
|
dec.pos += 8 |
|
return i |
|
case 'd': |
|
var f float64 |
|
dec.binread(&f) |
|
dec.pos += 8 |
|
return f |
|
case 's': |
|
length := dec.decode("u", depth).(uint32) |
|
b := make([]byte, int(length)+1) |
|
if _, err := io.ReadFull(dec.in, b); err != nil { |
|
panic(err) |
|
} |
|
dec.pos += int(length) + 1 |
|
return string(b[:len(b)-1]) |
|
case 'o': |
|
return ObjectPath(dec.decode("s", depth).(string)) |
|
case 'g': |
|
length := dec.decode("y", depth).(byte) |
|
b := make([]byte, int(length)+1) |
|
if _, err := io.ReadFull(dec.in, b); err != nil { |
|
panic(err) |
|
} |
|
dec.pos += int(length) + 1 |
|
sig, err := ParseSignature(string(b[:len(b)-1])) |
|
if err != nil { |
|
panic(err) |
|
} |
|
return sig |
|
case 'v': |
|
if depth >= 64 { |
|
panic(FormatError("input exceeds container depth limit")) |
|
} |
|
var variant Variant |
|
sig := dec.decode("g", depth).(Signature) |
|
if len(sig.str) == 0 { |
|
panic(FormatError("variant signature is empty")) |
|
} |
|
err, rem := validSingle(sig.str, 0) |
|
if err != nil { |
|
panic(err) |
|
} |
|
if rem != "" { |
|
panic(FormatError("variant signature has multiple types")) |
|
} |
|
variant.sig = sig |
|
variant.value = dec.decode(sig.str, depth+1) |
|
return variant |
|
case 'h': |
|
return UnixFDIndex(dec.decode("u", depth).(uint32)) |
|
case 'a': |
|
if len(s) > 1 && s[1] == '{' { |
|
ksig := s[2:3] |
|
vsig := s[3 : len(s)-1] |
|
v := reflect.MakeMap(reflect.MapOf(typeFor(ksig), typeFor(vsig))) |
|
if depth >= 63 { |
|
panic(FormatError("input exceeds container depth limit")) |
|
} |
|
length := dec.decode("u", depth).(uint32) |
|
// Even for empty maps, the correct padding must be included |
|
dec.align(8) |
|
spos := dec.pos |
|
for dec.pos < spos+int(length) { |
|
dec.align(8) |
|
if !isKeyType(v.Type().Key()) { |
|
panic(InvalidTypeError{v.Type()}) |
|
} |
|
kv := dec.decode(ksig, depth+2) |
|
vv := dec.decode(vsig, depth+2) |
|
v.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv)) |
|
} |
|
return v.Interface() |
|
} |
|
if depth >= 64 { |
|
panic(FormatError("input exceeds container depth limit")) |
|
} |
|
length := dec.decode("u", depth).(uint32) |
|
v := reflect.MakeSlice(reflect.SliceOf(typeFor(s[1:])), 0, int(length)) |
|
// Even for empty arrays, the correct padding must be included |
|
dec.align(alignment(typeFor(s[1:]))) |
|
spos := dec.pos |
|
for dec.pos < spos+int(length) { |
|
ev := dec.decode(s[1:], depth+1) |
|
v = reflect.Append(v, reflect.ValueOf(ev)) |
|
} |
|
return v.Interface() |
|
case '(': |
|
if depth >= 64 { |
|
panic(FormatError("input exceeds container depth limit")) |
|
} |
|
dec.align(8) |
|
v := make([]interface{}, 0) |
|
s = s[1 : len(s)-1] |
|
for s != "" { |
|
err, rem := validSingle(s, 0) |
|
if err != nil { |
|
panic(err) |
|
} |
|
ev := dec.decode(s[:len(s)-len(rem)], depth+1) |
|
v = append(v, ev) |
|
s = rem |
|
} |
|
return v |
|
default: |
|
panic(SignatureError{Sig: s}) |
|
} |
|
} |
|
|
|
// A FormatError is an error in the wire format. |
|
type FormatError string |
|
|
|
func (e FormatError) Error() string { |
|
return "dbus: wire format error: " + string(e) |
|
}
|
|
|