gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

decoder.go (6457B)


      1 package dbus
      2 
      3 import (
      4 	"encoding/binary"
      5 	"io"
      6 	"reflect"
      7 )
      8 
      9 type decoder struct {
     10 	in    io.Reader
     11 	order binary.ByteOrder
     12 	pos   int
     13 }
     14 
     15 // newDecoder returns a new decoder that reads values from in. The input is
     16 // expected to be in the given byte order.
     17 func newDecoder(in io.Reader, order binary.ByteOrder) *decoder {
     18 	dec := new(decoder)
     19 	dec.in = in
     20 	dec.order = order
     21 	return dec
     22 }
     23 
     24 // align aligns the input to the given boundary and panics on error.
     25 func (dec *decoder) align(n int) {
     26 	if dec.pos%n != 0 {
     27 		newpos := (dec.pos + n - 1) & ^(n - 1)
     28 		empty := make([]byte, newpos-dec.pos)
     29 		if _, err := io.ReadFull(dec.in, empty); err != nil {
     30 			panic(err)
     31 		}
     32 		dec.pos = newpos
     33 	}
     34 }
     35 
     36 // Calls binary.Read(dec.in, dec.order, v) and panics on read errors.
     37 func (dec *decoder) binread(v interface{}) {
     38 	if err := binary.Read(dec.in, dec.order, v); err != nil {
     39 		panic(err)
     40 	}
     41 }
     42 
     43 func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
     44 	defer func() {
     45 		var ok bool
     46 		v := recover()
     47 		if err, ok = v.(error); ok {
     48 			if err == io.EOF || err == io.ErrUnexpectedEOF {
     49 				err = FormatError("unexpected EOF")
     50 			}
     51 		}
     52 	}()
     53 	vs = make([]interface{}, 0)
     54 	s := sig.str
     55 	for s != "" {
     56 		err, rem := validSingle(s, 0)
     57 		if err != nil {
     58 			return nil, err
     59 		}
     60 		v := dec.decode(s[:len(s)-len(rem)], 0)
     61 		vs = append(vs, v)
     62 		s = rem
     63 	}
     64 	return vs, nil
     65 }
     66 
     67 func (dec *decoder) decode(s string, depth int) interface{} {
     68 	dec.align(alignment(typeFor(s)))
     69 	switch s[0] {
     70 	case 'y':
     71 		var b [1]byte
     72 		if _, err := dec.in.Read(b[:]); err != nil {
     73 			panic(err)
     74 		}
     75 		dec.pos++
     76 		return b[0]
     77 	case 'b':
     78 		i := dec.decode("u", depth).(uint32)
     79 		switch {
     80 		case i == 0:
     81 			return false
     82 		case i == 1:
     83 			return true
     84 		default:
     85 			panic(FormatError("invalid value for boolean"))
     86 		}
     87 	case 'n':
     88 		var i int16
     89 		dec.binread(&i)
     90 		dec.pos += 2
     91 		return i
     92 	case 'i':
     93 		var i int32
     94 		dec.binread(&i)
     95 		dec.pos += 4
     96 		return i
     97 	case 'x':
     98 		var i int64
     99 		dec.binread(&i)
    100 		dec.pos += 8
    101 		return i
    102 	case 'q':
    103 		var i uint16
    104 		dec.binread(&i)
    105 		dec.pos += 2
    106 		return i
    107 	case 'u':
    108 		var i uint32
    109 		dec.binread(&i)
    110 		dec.pos += 4
    111 		return i
    112 	case 't':
    113 		var i uint64
    114 		dec.binread(&i)
    115 		dec.pos += 8
    116 		return i
    117 	case 'd':
    118 		var f float64
    119 		dec.binread(&f)
    120 		dec.pos += 8
    121 		return f
    122 	case 's':
    123 		length := dec.decode("u", depth).(uint32)
    124 		b := make([]byte, int(length)+1)
    125 		if _, err := io.ReadFull(dec.in, b); err != nil {
    126 			panic(err)
    127 		}
    128 		dec.pos += int(length) + 1
    129 		return string(b[:len(b)-1])
    130 	case 'o':
    131 		return ObjectPath(dec.decode("s", depth).(string))
    132 	case 'g':
    133 		length := dec.decode("y", depth).(byte)
    134 		b := make([]byte, int(length)+1)
    135 		if _, err := io.ReadFull(dec.in, b); err != nil {
    136 			panic(err)
    137 		}
    138 		dec.pos += int(length) + 1
    139 		sig, err := ParseSignature(string(b[:len(b)-1]))
    140 		if err != nil {
    141 			panic(err)
    142 		}
    143 		return sig
    144 	case 'v':
    145 		if depth >= 64 {
    146 			panic(FormatError("input exceeds container depth limit"))
    147 		}
    148 		var variant Variant
    149 		sig := dec.decode("g", depth).(Signature)
    150 		if len(sig.str) == 0 {
    151 			panic(FormatError("variant signature is empty"))
    152 		}
    153 		err, rem := validSingle(sig.str, 0)
    154 		if err != nil {
    155 			panic(err)
    156 		}
    157 		if rem != "" {
    158 			panic(FormatError("variant signature has multiple types"))
    159 		}
    160 		variant.sig = sig
    161 		variant.value = dec.decode(sig.str, depth+1)
    162 		return variant
    163 	case 'h':
    164 		return UnixFDIndex(dec.decode("u", depth).(uint32))
    165 	case 'a':
    166 		if len(s) > 1 && s[1] == '{' {
    167 			ksig := s[2:3]
    168 			vsig := s[3 : len(s)-1]
    169 			v := reflect.MakeMap(reflect.MapOf(typeFor(ksig), typeFor(vsig)))
    170 			if depth >= 63 {
    171 				panic(FormatError("input exceeds container depth limit"))
    172 			}
    173 			length := dec.decode("u", depth).(uint32)
    174 			// Even for empty maps, the correct padding must be included
    175 			dec.align(8)
    176 			spos := dec.pos
    177 			for dec.pos < spos+int(length) {
    178 				dec.align(8)
    179 				if !isKeyType(v.Type().Key()) {
    180 					panic(InvalidTypeError{v.Type()})
    181 				}
    182 				kv := dec.decode(ksig, depth+2)
    183 				vv := dec.decode(vsig, depth+2)
    184 				v.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv))
    185 			}
    186 			return v.Interface()
    187 		}
    188 		if depth >= 64 {
    189 			panic(FormatError("input exceeds container depth limit"))
    190 		}
    191 		sig := s[1:]
    192 		length := dec.decode("u", depth).(uint32)
    193 		// capacity can be determined only for fixed-size element types
    194 		var capacity int
    195 		if s := sigByteSize(sig); s != 0 {
    196 			capacity = int(length) / s
    197 		}
    198 		v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity)
    199 		// Even for empty arrays, the correct padding must be included
    200 		align := alignment(typeFor(s[1:]))
    201 		if len(s) > 1 && s[1] == '(' {
    202 			//Special case for arrays of structs
    203 			//structs decode as a slice of interface{} values
    204 			//but the dbus alignment does not match this
    205 			align = 8
    206 		}
    207 		dec.align(align)
    208 		spos := dec.pos
    209 		for dec.pos < spos+int(length) {
    210 			ev := dec.decode(s[1:], depth+1)
    211 			v = reflect.Append(v, reflect.ValueOf(ev))
    212 		}
    213 		return v.Interface()
    214 	case '(':
    215 		if depth >= 64 {
    216 			panic(FormatError("input exceeds container depth limit"))
    217 		}
    218 		dec.align(8)
    219 		v := make([]interface{}, 0)
    220 		s = s[1 : len(s)-1]
    221 		for s != "" {
    222 			err, rem := validSingle(s, 0)
    223 			if err != nil {
    224 				panic(err)
    225 			}
    226 			ev := dec.decode(s[:len(s)-len(rem)], depth+1)
    227 			v = append(v, ev)
    228 			s = rem
    229 		}
    230 		return v
    231 	default:
    232 		panic(SignatureError{Sig: s})
    233 	}
    234 }
    235 
    236 // sigByteSize tries to calculates size of the given signature in bytes.
    237 //
    238 // It returns zero when it can't, for example when it contains non-fixed size
    239 // types such as strings, maps and arrays that require reading of the transmitted
    240 // data, for that we would need to implement the unread method for Decoder first.
    241 func sigByteSize(sig string) int {
    242 	var total int
    243 	for offset := 0; offset < len(sig); {
    244 		switch sig[offset] {
    245 		case 'y':
    246 			total += 1
    247 			offset += 1
    248 		case 'n', 'q':
    249 			total += 2
    250 			offset += 1
    251 		case 'b', 'i', 'u', 'h':
    252 			total += 4
    253 			offset += 1
    254 		case 'x', 't', 'd':
    255 			total += 8
    256 			offset += 1
    257 		case '(':
    258 			i := 1
    259 			depth := 1
    260 			for i < len(sig[offset:]) && depth != 0 {
    261 				if sig[offset+i] == '(' {
    262 					depth++
    263 				} else if sig[offset+i] == ')' {
    264 					depth--
    265 				}
    266 				i++
    267 			}
    268 			s := sigByteSize(sig[offset+1 : offset+i-1])
    269 			if s == 0 {
    270 				return 0
    271 			}
    272 			total += s
    273 			offset += i
    274 		default:
    275 			return 0
    276 		}
    277 	}
    278 	return total
    279 }
    280 
    281 // A FormatError is an error in the wire format.
    282 type FormatError string
    283 
    284 func (e FormatError) Error() string {
    285 	return "dbus: wire format error: " + string(e)
    286 }