예제 #1
0
func decodeSlice(d *decodeState, kind int, v reflect.Value) {
	if kind != kindArray {
		d.saveErrorAndSkip(kind, v.Type())
		return
	}
	t := v.Type()
	offset := d.beginDoc()
	i := 0
	for {
		kind, _ := d.scanKindName()
		if kind == 0 {
			break
		}
		if i >= v.Cap() {
			newcap := v.Cap() + v.Cap()/2
			if newcap < 4 {
				newcap = 4
			}
			newv := reflect.MakeSlice(t, v.Len(), newcap)
			reflect.Copy(newv, v)
			v.Set(newv)
		}
		if i >= v.Len() {
			v.SetLen(i + 1)
		}
		d.decodeValue(kind, v.Index(i))
		i += 1
	}
	d.endDoc(offset)
}
예제 #2
0
파일: decode.go 프로젝트: MG-RAST/Shock
func (f *decFnInfo) kSlice(rv reflect.Value) {
	// A slice can be set from a map or array in stream.
	currEncodedType := f.dd.currentEncodedType()

	switch currEncodedType {
	case valueTypeBytes, valueTypeString:
		if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
			if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
				rv.SetBytes(bs2)
			}
			return
		}
	}

	if shortCircuitReflectToFastPath && rv.CanAddr() {
		switch f.ti.rtid {
		case intfSliceTypId:
			f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}), currEncodedType, f.array)
			return
		case uint64SliceTypId:
			f.d.decSliceUint64(rv.Addr().Interface().(*[]uint64), currEncodedType, f.array)
			return
		case int64SliceTypId:
			f.d.decSliceInt64(rv.Addr().Interface().(*[]int64), currEncodedType, f.array)
			return
		case strSliceTypId:
			f.d.decSliceStr(rv.Addr().Interface().(*[]string), currEncodedType, f.array)
			return
		}
	}

	containerLen, containerLenS := decContLens(f.dd, currEncodedType)

	// an array can never return a nil slice. so no need to check f.array here.

	if rv.IsNil() {
		rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
	}

	if containerLen == 0 {
		return
	}

	if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
		if f.array { // !rv.CanSet()
			decErr(msgDecCannotExpandArr, rvcap, containerLenS)
		}
		rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
		if rvlen > 0 {
			reflect.Copy(rvn, rv)
		}
		rv.Set(rvn)
	} else if containerLenS > rvlen {
		rv.SetLen(containerLenS)
	}

	for j := 0; j < containerLenS; j++ {
		f.d.decodeValue(rv.Index(j))
	}
}
예제 #3
0
func setRepeated(field reflect.Value, vslice []Value, setElem setFunc) error {
	vlen := len(vslice)
	var flen int
	switch field.Type().Kind() {
	case reflect.Slice:
		// Make a slice of the right size, avoiding allocation if possible.
		switch {
		case field.Len() < vlen:
			field.Set(reflect.MakeSlice(field.Type(), vlen, vlen))
		case field.Len() > vlen:
			field.SetLen(vlen)
		}
		flen = vlen

	case reflect.Array:
		flen = field.Len()
		if flen > vlen {
			// Set extra elements to their zero value.
			z := reflect.Zero(field.Type().Elem())
			for i := vlen; i < flen; i++ {
				field.Index(i).Set(z)
			}
		}
	default:
		return fmt.Errorf("bigquery: impossible field type %s", field.Type())
	}
	for i, val := range vslice {
		if i < flen { // avoid writing past the end of a short array
			if err := setElem(field.Index(i), val); err != nil {
				return err
			}
		}
	}
	return nil
}
예제 #4
0
func (d *Decoder) decodeList(avList []*dynamodb.AttributeValue, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Slice:
		// Make room for the slice elements if needed
		if v.IsNil() || v.Cap() < len(avList) {
			// What about if ignoring nil/empty values?
			v.Set(reflect.MakeSlice(v.Type(), 0, len(avList)))
		}
	case reflect.Array:
		// Limited to capacity of existing array.
	case reflect.Interface:
		s := make([]interface{}, len(avList))
		for i, av := range avList {
			if err := d.decode(av, reflect.ValueOf(&s[i]).Elem(), tag{}); err != nil {
				return err
			}
		}
		v.Set(reflect.ValueOf(s))
		return nil
	default:
		return &UnmarshalTypeError{Value: "list", Type: v.Type()}
	}

	// If v is not a slice, array
	for i := 0; i < v.Cap() && i < len(avList); i++ {
		v.SetLen(i + 1)
		if err := d.decode(avList[i], v.Index(i), tag{}); err != nil {
			return err
		}
	}

	return nil
}
예제 #5
0
func (d *Decoder) decodeBinary(b []byte, v reflect.Value) error {
	if v.Kind() == reflect.Interface {
		buf := make([]byte, len(b))
		copy(buf, b)
		v.Set(reflect.ValueOf(buf))
		return nil
	}

	switch v.Interface().(type) {
	case []byte:
		if v.IsNil() || v.Cap() < len(b) {
			v.Set(reflect.MakeSlice(byteSliceType, len(b), len(b)))
		} else if v.Len() != len(b) {
			v.SetLen(len(b))
		}
		copy(v.Interface().([]byte), b)
	default:
		if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 {
			reflect.Copy(v, reflect.ValueOf(b))
			break
		}
		return &UnmarshalTypeError{Value: "binary", Type: v.Type()}
	}

	return nil
}
예제 #6
0
func (d *Decoder) decodeStringSet(ss []*string, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Slice:
		// Make room for the slice elements if needed
		if v.IsNil() || v.Cap() < len(ss) {
			v.Set(reflect.MakeSlice(v.Type(), 0, len(ss)))
		}
	case reflect.Array:
		// Limited to capacity of existing array.
	case reflect.Interface:
		set := make([]string, len(ss))
		for i, s := range ss {
			if err := d.decodeString(s, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil {
				return err
			}
		}
		v.Set(reflect.ValueOf(set))
		return nil
	default:
		return &UnmarshalTypeError{Value: "string set", Type: v.Type()}
	}

	for i := 0; i < v.Cap() && i < len(ss); i++ {
		v.SetLen(i + 1)
		u, elem := indirect(v.Index(i), false)
		if u != nil {
			return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{SS: ss})
		}
		if err := d.decodeString(ss[i], elem, tag{}); err != nil {
			return err
		}
	}

	return nil
}
예제 #7
0
파일: parse.go 프로젝트: alexflint/go-arg
// parse a value as the appropriate type and store it in the struct
func setSlice(dest reflect.Value, values []string) error {
	if !dest.CanSet() {
		return fmt.Errorf("field is not writable")
	}

	var ptr bool
	elem := dest.Type().Elem()
	if elem.Kind() == reflect.Ptr {
		ptr = true
		elem = elem.Elem()
	}

	// Truncate the dest slice in case default values exist
	if !dest.IsNil() {
		dest.SetLen(0)
	}

	for _, s := range values {
		v := reflect.New(elem)
		if err := setScalar(v.Elem(), s); err != nil {
			return err
		}
		if !ptr {
			v = v.Elem()
		}
		dest.Set(reflect.Append(dest, v))
	}
	return nil
}
예제 #8
0
파일: scan.go 프로젝트: 42wim/ulog2queue
func ensureLen(d reflect.Value, n int) {
	if n > d.Cap() {
		d.Set(reflect.MakeSlice(d.Type(), n, n))
	} else {
		d.SetLen(n)
	}
}
예제 #9
0
func (p *Decoder) unmarshalArray(pval *plistValue, val reflect.Value) {
	subvalues := pval.value.([]*plistValue)

	var n int
	if val.Kind() == reflect.Slice {
		// Slice of element values.
		// Grow slice.
		cnt := len(subvalues) + val.Len()
		if cnt >= val.Cap() {
			ncap := 2 * cnt
			if ncap < 4 {
				ncap = 4
			}
			new := reflect.MakeSlice(val.Type(), val.Len(), ncap)
			reflect.Copy(new, val)
			val.Set(new)
		}
		n = val.Len()
		val.SetLen(cnt)
	} else if val.Kind() == reflect.Array {
		if len(subvalues) > val.Cap() {
			panic(fmt.Errorf("plist: attempted to unmarshal %d values into an array of size %d", len(subvalues), val.Cap()))
		}
	} else {
		panic(&incompatibleDecodeTypeError{val.Type(), pval.kind})
	}

	// Recur to read element into slice.
	for _, sval := range subvalues {
		p.unmarshal(sval, val.Index(n))
		n++
	}
	return
}
예제 #10
0
func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error {
	i := 0
	for ; ; i++ {
		// grow slice if necessary
		if i >= val.Cap() {
			newcap := val.Cap() + val.Cap()/2
			if newcap < 4 {
				newcap = 4
			}
			newv := reflect.MakeSlice(val.Type(), val.Len(), newcap)
			reflect.Copy(newv, val)
			val.Set(newv)
		}
		if i >= val.Len() {
			val.SetLen(i + 1)
		}
		// decode into element
		if err := elemdec(s, val.Index(i)); err == EOL {
			break
		} else if err != nil {
			return addErrorContext(err, fmt.Sprint("[", i, "]"))
		}
	}
	if i < val.Len() {
		val.SetLen(i)
	}
	return nil
}
예제 #11
0
func (d *Decoder) decodeSlice(valueField reflect.Value, key string) error {
	//fmt.Printf("[D] Decode slice tagged as: ->%s<-\n", key)

	var errors []string
	seenIndexes := make(map[string]bool)

	for k := range d.vmx {
		if !strings.HasPrefix(k, key) {
			continue
		}

		index := getVMXAttrIndex(k, key)
		if index == "" || seenIndexes[index] {
			continue
		}

		// The reason we have to keep track of seen indexes is because entries
		// in the vmx file with the same prefix are actually objects, they are
		// decoded into Go structs, meaning that they only need one pass to be decoded.
		seenIndexes[index] = true

		length := valueField.Len()
		capacity := valueField.Cap()

		// Grow the slice if needed. This allows us to pass a value
		// reference to d.decode() so it populates the value addressed by the slice.
		if length >= capacity {
			capacity := 2 * length
			if capacity < 4 {
				capacity = 4
			}

			newSlice := reflect.MakeSlice(valueField.Type(), length, capacity)
			reflect.Copy(newSlice, valueField)
			valueField.Set(newSlice)
		}

		valueField.SetLen(length + 1)

		newKey := key
		if key != index {
			newKey = key + index
		}

		err := d.decode(valueField.Index(length), newKey)

		if err != nil {
			errors = appendErrors(errors, err)
			valueField.SetLen(length)
		}
	}

	if len(errors) > 0 {
		return &Error{errors}
	}

	return nil
}
예제 #12
0
파일: decode.go 프로젝트: jmptrader/bencode
func (d *Decoder) decodeList(v reflect.Value) error {
	//if we have an interface, just put a []interface{} in it!
	if v.Kind() == reflect.Interface {
		var x []interface{}
		defer func(p reflect.Value) { p.Set(v) }(v)
		v = reflect.ValueOf(&x).Elem()
	}

	if v.Kind() != reflect.Array && v.Kind() != reflect.Slice {
		return fmt.Errorf("Cant store a []interface{} into %s", v.Type())
	}

	//read out the l that prefixes the list
	ch, err := d.readByte()
	if err != nil {
		return err
	}
	if ch != 'l' {
		panic("got something other than a list head after a peek")
	}

	for i := 0; ; i++ {
		//peek for the end token and read it out
		ch, err := d.peekByte()
		if err != nil {
			return err
		}
		switch ch {
		case 'e':
			_, err := d.readByte() //consume the end
			return err
		}

		//grow it if required
		if i >= v.Cap() && v.IsValid() {
			newcap := v.Cap() + v.Cap()/2
			if newcap < 4 {
				newcap = 4
			}
			newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
			reflect.Copy(newv, v)
			v.Set(newv)
		}

		//reslice into cap (its a slice now since it had to have grown)
		if i >= v.Len() && v.IsValid() {
			v.SetLen(i + 1)
		}

		//decode a value into the index
		if err := d.decodeInto(v.Index(i)); err != nil {
			return err
		}
	}

	panic("unreachable")
}
예제 #13
0
파일: decode.go 프로젝트: qiangmzsx/golang
//FIXME: fix when v is invalid
// type(1) | name length(1) | item size(4) | raw name bytes | 0x00
// | element number(4) | element1 | ... | elementN
func (d *decodeState) array(v reflect.Value) {
	d.off += 1 // type

	klen := int(Int8(d.data[d.off:]))
	d.off += 1 // name length

	// vlen := int(Int32(d.data[d.off:]))
	d.off += 4 //  content length

	//var key string
	if klen > 0 {
		key := d.data[d.off : d.off+klen-1]
		d.off += klen
		v = fieldByTag(v, key)
		u, pv := d.indirect(v, false)
		if u != nil {
			d.off -= 1 + 1 + 4 + klen
			if err := u.UnmarshalMCPACK(d.next()); err != nil {
				d.error(err)
			}
			return
		}
		v = pv
	}

	n := int(Int32(d.data[d.off:]))
	d.off += 4 // member number

	if v.Kind() == reflect.Slice {
		if n > v.Cap() {
			newv := reflect.MakeSlice(v.Type(), n, n)
			v.Set(newv)
		}
		v.SetLen(n)
	}

	for i := 0; i < n; i++ {
		if i < v.Len() {
			d.value(v.Index(i))
		} else {
			d.value(reflect.Value{})
		}
	}

	if n < v.Len() {
		if v.Kind() == reflect.Array {
			z := reflect.Zero(v.Type().Elem())
			for i := 0; i < v.Len(); i++ {
				v.Index(i).Set(z)
			}
		}
	}

	if n == 0 && v.Kind() == reflect.Slice {
		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
	}
}
예제 #14
0
func fixSliceLen(slice reflect.Value, lenslice int) reflect.Value {
	if slice.Len() != lenslice {
		if slice.Cap() >= lenslice {
			slice.SetLen(lenslice)
		} else {
			slice.Set(reflect.MakeSlice(slice.Type(), lenslice, lenslice))
		}
	}
	return slice
}
예제 #15
0
파일: read.go 프로젝트: achanda/go
// unmarshalAttr unmarshals a single XML attribute into val.
func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
	if val.Kind() == reflect.Ptr {
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}
		val = val.Elem()
	}
	if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
		// This is an unmarshaler with a non-pointer receiver,
		// so it's likely to be incorrect, but we do what we're told.
		return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
	}
	if val.CanAddr() {
		pv := val.Addr()
		if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
			return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
		}
	}

	// Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
	if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
		// This is an unmarshaler with a non-pointer receiver,
		// so it's likely to be incorrect, but we do what we're told.
		return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
	}
	if val.CanAddr() {
		pv := val.Addr()
		if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
			return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
		}
	}

	if val.Type().Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
		// Slice of element values.
		// Grow slice.
		n := val.Len()
		val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))

		// Recur to read element into slice.
		if err := p.unmarshalAttr(val.Index(n), attr); err != nil {
			val.SetLen(n)
			return err
		}
		return nil
	}

	if val.Type() == attrType {
		val.Set(reflect.ValueOf(attr))
		return nil
	}

	return copyValue(val, []byte(attr.Value))
}
예제 #16
0
파일: decode.go 프로젝트: kjplatz/vic
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
	datav := reflect.ValueOf(data)
	if datav.Kind() != reflect.Slice {
		return badtype("slice", data)
	}
	sliceLen := datav.Len()
	if rv.IsNil() || rv.Len() < datav.Len() {
		rv.Set(reflect.MakeSlice(rv.Type(), sliceLen, sliceLen))
	}
	rv.SetLen(datav.Len())
	return md.unifySliceArray(datav, rv)
}
예제 #17
0
파일: config.go 프로젝트: kho/easy
func setSlice(value reflect.Value, args []string) (n int, err error) {
	value.SetLen(0)
	slice := value
	for _, i := range args {
		x := reflect.New(value.Type().Elem())
		if err = setValue(x.Elem(), i); err != nil {
			return
		}
		slice = reflect.Append(slice, x.Elem())
		n++
	}
	value.Set(slice)
	return
}
예제 #18
0
파일: decode.go 프로젝트: Zenithar/dgabloom
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
	datav := reflect.ValueOf(data)
	if datav.Kind() != reflect.Slice {
		if !datav.IsValid() {
			return nil
		}
		return badtype("slice", data)
	}
	n := datav.Len()
	if rv.IsNil() || rv.Cap() < n {
		rv.Set(reflect.MakeSlice(rv.Type(), n, n))
	}
	rv.SetLen(n)
	return md.unifySliceArray(datav, rv)
}
예제 #19
0
func (f *decFnInfo) kSlice(rv reflect.Value) {
	// A slice can be set from a map or array in stream.
	currEncodedType := f.dd.currentEncodedType()

	switch currEncodedType {
	case valueTypeBytes, valueTypeString:
		if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
			if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
				rv.SetBytes(bs2)
			}
			return
		}
	}

	containerLen, containerLenS := decContLens(f.dd, currEncodedType)

	// an array can never return a nil slice. so no need to check f.array here.

	if rv.IsNil() {
		rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
	}

	if containerLen == 0 {
		return
	}

	if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
		if f.array { // !rv.CanSet()
			decErr(msgDecCannotExpandArr, rvcap, containerLenS)
		}
		rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
		if rvlen > 0 {
			reflect.Copy(rvn, rv)
		}
		rv.Set(rvn)
	} else if containerLenS > rvlen {
		rv.SetLen(containerLenS)
	}

	rtelem := f.ti.rt.Elem()
	for rtelem.Kind() == reflect.Ptr {
		rtelem = rtelem.Elem()
	}
	fn := f.d.getDecFn(rtelem)
	for j := 0; j < containerLenS; j++ {
		f.d.decodeValue(rv.Index(j), fn)
	}
}
예제 #20
0
func decodeByteSlice(d *decodeState, kind int, v reflect.Value) {
	var p []byte
	switch kind {
	default:
		d.saveErrorAndSkip(kind, v.Type())
		return
	case kindBinary:
		p, _ = d.scanBinary()
	}
	if v.IsNil() || v.Cap() < len(p) {
		v.Set(reflect.MakeSlice(v.Type(), len(p), len(p)))
	} else {
		v.SetLen(len(p))
	}
	reflect.Copy(v, reflect.ValueOf(p))
}
예제 #21
0
func (d *Decoder) decodeNumberSet(ns []*string, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Slice:
		// Make room for the slice elements if needed
		if v.IsNil() || v.Cap() < len(ns) {
			// What about if ignoring nil/empty values?
			v.Set(reflect.MakeSlice(v.Type(), 0, len(ns)))
		}
	case reflect.Array:
		// Limited to capacity of existing array.
	case reflect.Interface:
		if d.UseNumber {
			set := make([]Number, len(ns))
			for i, n := range ns {
				if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem()); err != nil {
					return err
				}
			}
			v.Set(reflect.ValueOf(set))
		} else {
			set := make([]float64, len(ns))
			for i, n := range ns {
				if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem()); err != nil {
					return err
				}
			}
			v.Set(reflect.ValueOf(set))
		}
		return nil
	default:
		return &UnmarshalTypeError{Value: "number set", Type: v.Type()}
	}

	for i := 0; i < v.Cap() && i < len(ns); i++ {
		v.SetLen(i + 1)
		u, elem := indirect(v.Index(i), false)
		if u != nil {
			return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{NS: ns})
		}
		if err := d.decodeNumber(ns[i], elem); err != nil {
			return err
		}
	}

	return nil
}
예제 #22
0
func (c *Config) configureArray(v, config reflect.Value, path string) error {
	vkind := v.Kind()

	// nil interface
	if vkind == reflect.Interface && v.NumMethod() == 0 {
		v.Set(config)
		return nil
	}

	if vkind != reflect.Array && vkind != reflect.Slice {
		return &ConfigValueError{path, fmt.Sprintf("%v cannot be used to configure %v", config.Type(), v.Type())}
	}

	n := config.Len()

	// grow slice if it's smaller than the config array
	if vkind == reflect.Slice && v.Cap() < n {
		t := reflect.MakeSlice(v.Type(), n, n)
		reflect.Copy(t, v)
		v.Set(t)
	}

	if n > v.Cap() {
		n = v.Cap()
	}
	for i := 0; i < n; i++ {
		if err := c.configure(v.Index(i), config.Index(i), path+"."+strconv.Itoa(i)); err != nil {
			return err
		}
	}

	if n < v.Len() {
		if vkind == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(v.Type().Elem())
			for i := n; i < v.Len(); i++ {
				v.Index(i).Set(z)
			}
		} else {
			v.SetLen(n)
		}
	}

	return nil
}
예제 #23
0
파일: decode.go 프로젝트: nsf/libtorgo
func (d *decoder) parse_list(v reflect.Value) {
	switch v.Kind() {
	case reflect.Array, reflect.Slice:
	default:
		panic(&UnmarshalTypeError{
			Value: "array",
			Type:  v.Type(),
		})
	}

	i := 0
	for {
		if v.Kind() == reflect.Slice && i >= v.Len() {
			v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))
		}

		ok := false
		if i < v.Len() {
			ok = d.parse_value(v.Index(i))
		} else {
			_, ok = d.parse_value_interface()
		}

		if !ok {
			break
		}

		i++
	}

	if i < v.Len() {
		if v.Kind() == reflect.Array {
			z := reflect.Zero(v.Type().Elem())
			for n := v.Len(); i < n; i++ {
				v.Index(i).Set(z)
			}
		} else {
			v.SetLen(i)
		}
	}

	if i == 0 && v.Kind() == reflect.Slice {
		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
	}
}
예제 #24
0
func (d *Decoder) decodeBinary(b []byte, v reflect.Value) error {
	if v.Kind() == reflect.Interface {
		buf := make([]byte, len(b))
		copy(buf, b)
		v.Set(reflect.ValueOf(buf))
		return nil
	}

	if v.Kind() != reflect.Slice {
		return &UnmarshalTypeError{Value: "binary", Type: v.Type()}
	}

	if v.Type() == byteSliceType {
		// Optimization for []byte types
		if v.IsNil() || v.Cap() < len(b) {
			v.Set(reflect.MakeSlice(byteSliceType, len(b), len(b)))
		} else if v.Len() != len(b) {
			v.SetLen(len(b))
		}
		copy(v.Interface().([]byte), b)
		return nil
	}

	switch v.Type().Elem().Kind() {
	case reflect.Uint8:
		// Fallback to reflection copy for type aliased of []byte type
		if v.IsNil() || v.Cap() < len(b) {
			v.Set(reflect.MakeSlice(v.Type(), len(b), len(b)))
		} else if v.Len() != len(b) {
			v.SetLen(len(b))
		}
		for i := 0; i < len(b); i++ {
			v.Index(i).SetUint(uint64(b[i]))
		}
	default:
		if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 {
			reflect.Copy(v, reflect.ValueOf(b))
			break
		}
		return &UnmarshalTypeError{Value: "binary", Type: v.Type()}
	}

	return nil
}
예제 #25
0
파일: decode.go 프로젝트: davecgh/go-xdr
// decodeArray treats the next bytes as a variable length series of XDR encoded
// elements of the same type as the array represented by the reflection value.
// The number of elements is obtained by first decoding the unsigned integer
// element count.  Then each element is decoded into the passed array. The
// ignoreOpaque flag controls whether or not uint8 (byte) elements should be
// decoded individually or as a variable sequence of opaque data.  It returns
// the number of bytes actually read.
//
// An UnmarshalError is returned if any issues are encountered while decoding
// the array elements.
//
// Reference:
// 	RFC Section 4.13 - Variable-Length Array
// 	Unsigned integer length followed by individually XDR encoded array
// 	elements
func (d *Decoder) decodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
	dataLen, n, err := d.DecodeUint()
	if err != nil {
		return n, err
	}
	if uint(dataLen) > uint(math.MaxInt32) ||
		(d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
		err := unmarshalError("decodeArray", ErrOverflow, errMaxSlice,
			dataLen, nil)
		return n, err
	}

	// Allocate storage for the slice elements (the underlying array) if
	// existing slice does not have enough capacity.
	sliceLen := int(dataLen)
	if v.Cap() < sliceLen {
		v.Set(reflect.MakeSlice(v.Type(), sliceLen, sliceLen))
	}
	if v.Len() < sliceLen {
		v.SetLen(sliceLen)
	}

	// Treat []byte (byte is alias for uint8) as opaque data unless ignored.
	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
		data, n2, err := d.DecodeFixedOpaque(int32(sliceLen))
		n += n2
		if err != nil {
			return n, err
		}
		v.SetBytes(data)
		return n, nil
	}

	// Decode each slice element.
	for i := 0; i < sliceLen; i++ {
		n2, err := d.decode(v.Index(i))
		n += n2
		if err != nil {
			return n, err
		}
	}
	return n, nil
}
예제 #26
0
func unmarshalArray(data string, v reflect.Value, kind reflect.Kind) error {
	i := 0
	vtype := v.Type()
	l := v.Cap()
	if v.Len() < l {
		v.SetLen(l)
	}
	for len(data) > 0 {
		if i >= l {
			if kind == reflect.Array {
				break
			}
			newl := l + l/2
			if newl < 4 {
				newl = 4
			}
			newv := reflect.MakeSlice(vtype, newl, newl)
			reflect.Copy(newv, v)
			v.Set(newv)
			l = newl
		}
		el := v.Index(i)
		i++
		n, err := unmarshal(data, el)
		data = data[n:]
		if err != nil {
			return err
		}
	}
	if i < l {
		if kind == reflect.Array {
			// zero out the rest
			z := reflect.Zero(vtype.Elem())
			for ; i < l; i++ {
				v.Index(i).Set(z)
			}
		} else {
			v.SetLen(i)
		}
	}
	return nil
}
예제 #27
0
func (d *arrayDecoder) decode(dv, sv reflect.Value) {
	// Iterate through the slice/array and decode each element before adding it
	// to the dest slice/array
	i := 0
	for i < sv.Len() {
		if dv.Kind() == reflect.Slice {
			// Get element of array, growing if necessary.
			if i >= dv.Cap() {
				newcap := dv.Cap() + dv.Cap()/2
				if newcap < 4 {
					newcap = 4
				}
				newdv := reflect.MakeSlice(dv.Type(), dv.Len(), newcap)
				reflect.Copy(newdv, dv)
				dv.Set(newdv)
			}
			if i >= dv.Len() {
				dv.SetLen(i + 1)
			}
		}

		if i < dv.Len() {
			// Decode into element.
			d.elemDec(dv.Index(i), sv.Index(i))
		}

		i++
	}

	// Ensure that the destination is the correct size
	if i < dv.Len() {
		if dv.Kind() == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(dv.Type().Elem())
			for ; i < dv.Len(); i++ {
				dv.Index(i).Set(z)
			}
		} else {
			dv.SetLen(i)
		}
	}
}
예제 #28
0
파일: decode.go 프로젝트: niltonkummer/go
func (f *decFnInfo) kSlice(rv reflect.Value) {
	// Be more careful calling Set() here, because a reflect.Value from an array
	// may have come in here (which may not be settable).
	// In places where the slice got from an array could be, we should guard with CanSet() calls.

	if f.rtid == byteSliceTypId { // rawbytes
		if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
			rv.SetBytes(bs2)
		}
		return
	}

	containerLen := f.dd.readArrayLen()

	if rv.IsNil() {
		rv.Set(reflect.MakeSlice(f.rt, containerLen, containerLen))
	}
	if containerLen == 0 {
		return
	}

	// if we need to reset rv but it cannot be set, we should err out.
	// for example, if slice is got from unaddressable array, CanSet = false
	if rvcap, rvlen := rv.Len(), rv.Cap(); containerLen > rvcap {
		if rv.CanSet() {
			rvn := reflect.MakeSlice(f.rt, containerLen, containerLen)
			if rvlen > 0 {
				reflect.Copy(rvn, rv)
			}
			rv.Set(rvn)
		} else {
			decErr("Cannot reset slice with less cap: %v than stream contents: %v", rvcap, containerLen)
		}
	} else if containerLen > rvlen {
		rv.SetLen(containerLen)
	}
	for j := 0; j < containerLen; j++ {
		f.d.decodeValue(rv.Index(j))
	}
}
예제 #29
0
// setElement ses the element value of a map, array, or slice at the specified index.
func setElement(data reflect.Value, p string, v interface{}) error {
	value := reflect.ValueOf(v)
	switch data.Kind() {
	case reflect.Map:
		key := reflect.ValueOf(p)
		data.SetMapIndex(key, value)
	case reflect.Slice, reflect.Array:
		idx, err := strconv.Atoi(p)
		if err != nil || idx < 0 {
			return fmt.Errorf("%v is not a valid array or slice index", p)
		}
		if data.Kind() == reflect.Slice {
			if idx >= data.Cap() {
				return fmt.Errorf("%v is out of the slice index bound", p)
			}
			data.SetLen(idx + 1)
		} else if idx >= data.Cap() {
			return fmt.Errorf("%v is out of the array index bound", p)
		}
		data.Index(idx).Set(value)
	}
	return nil
}
예제 #30
0
파일: parsers.go 프로젝트: rymis/parse
func (par *sliceParser) ParseValue(ctx *parseContext, valueOf reflect.Value, location int, err *Error) int {
	var v reflect.Value

	valueOf.SetLen(0)
	tp := valueOf.Type().Elem()
	for {
		v = reflect.New(tp).Elem()
		var nl int

		nl = ctx.parse(v, par.Parser, location, err)
		if nl < 0 {
			if valueOf.Len() >= par.Min {
				return location
			}

			return nl
		}

		if nl <= location {
			panic("Invalid grammar: 0-length member of ZeroOrMore")
		}

		location = nl
		valueOf.Set(reflect.Append(valueOf, v))

		if len(par.Delimiter) > 0 {
			nl = ctx.skipWS(location)

			if strAt(ctx.str, nl, par.Delimiter) {
				location = ctx.skipWS(nl + len(par.Delimiter))
			} else {
				// Here we've got at least one parsed member, so it could not be an error.
				return nl
			}
		}
	}
}