func unmarshal()

in go/pkg/amqp/unmarshal.go [291:531]


func unmarshal(v interface{}, data *C.pn_data_t) {
	rt := reflect.TypeOf(v)
	rv := reflect.ValueOf(v)
	panicUnless(v != nil && rt.Kind() == reflect.Ptr && !rv.IsNil(), data, v)

	// Check for PN_DESCRIBED first, as described types can unmarshal into any of the Go types.
	// An interface{} target is handled in the switch below, even for described types.
	if _, isInterface := v.(*interface{}); !isInterface && bool(C.pn_data_is_described(data)) {
		getDescribed(data, v)
		return
	}

	// Unmarshal based on the target type
	pnType := C.pn_data_type(data)
	switch v := v.(type) {

	case *bool:
		panicUnless(pnType == C.PN_BOOL, data, v)
		*v = bool(C.pn_data_get_bool(data))

	case *int8:
		panicUnless(pnType == C.PN_BYTE, data, v)
		*v = int8(C.pn_data_get_byte(data))

	case *uint8:
		panicUnless(pnType == C.PN_UBYTE, data, v)
		*v = uint8(C.pn_data_get_ubyte(data))

	case *int16:
		switch C.pn_data_type(data) {
		case C.PN_BYTE:
			*v = int16(C.pn_data_get_byte(data))
		case C.PN_SHORT:
			*v = int16(C.pn_data_get_short(data))
		default:
			doPanic(data, v)
		}

	case *uint16:
		switch pnType {
		case C.PN_UBYTE:
			*v = uint16(C.pn_data_get_ubyte(data))
		case C.PN_USHORT:
			*v = uint16(C.pn_data_get_ushort(data))
		default:
			doPanic(data, v)
		}

	case *int32:
		switch pnType {
		case C.PN_CHAR:
			*v = int32(C.pn_data_get_char(data))
		case C.PN_BYTE:
			*v = int32(C.pn_data_get_byte(data))
		case C.PN_SHORT:
			*v = int32(C.pn_data_get_short(data))
		case C.PN_INT:
			*v = int32(C.pn_data_get_int(data))
		default:
			doPanic(data, v)
		}

	case *uint32:
		switch pnType {
		case C.PN_CHAR:
			*v = uint32(C.pn_data_get_char(data))
		case C.PN_UBYTE:
			*v = uint32(C.pn_data_get_ubyte(data))
		case C.PN_USHORT:
			*v = uint32(C.pn_data_get_ushort(data))
		case C.PN_UINT:
			*v = uint32(C.pn_data_get_uint(data))
		default:
			doPanic(data, v)
		}

	case *int64:
		switch pnType {
		case C.PN_CHAR:
			*v = int64(C.pn_data_get_char(data))
		case C.PN_BYTE:
			*v = int64(C.pn_data_get_byte(data))
		case C.PN_SHORT:
			*v = int64(C.pn_data_get_short(data))
		case C.PN_INT:
			*v = int64(C.pn_data_get_int(data))
		case C.PN_LONG:
			*v = int64(C.pn_data_get_long(data))
		default:
			doPanic(data, v)
		}

	case *uint64:
		switch pnType {
		case C.PN_CHAR:
			*v = uint64(C.pn_data_get_char(data))
		case C.PN_UBYTE:
			*v = uint64(C.pn_data_get_ubyte(data))
		case C.PN_USHORT:
			*v = uint64(C.pn_data_get_ushort(data))
		case C.PN_ULONG:
			*v = uint64(C.pn_data_get_ulong(data))
		default:
			doPanic(data, v)
		}

	case *int:
		switch pnType {
		case C.PN_CHAR:
			*v = int(C.pn_data_get_char(data))
		case C.PN_BYTE:
			*v = int(C.pn_data_get_byte(data))
		case C.PN_SHORT:
			*v = int(C.pn_data_get_short(data))
		case C.PN_INT:
			*v = int(C.pn_data_get_int(data))
		case C.PN_LONG:
			if intIs64 {
				*v = int(C.pn_data_get_long(data))
			} else {
				doPanic(data, v)
			}
		default:
			doPanic(data, v)
		}

	case *uint:
		switch pnType {
		case C.PN_CHAR:
			*v = uint(C.pn_data_get_char(data))
		case C.PN_UBYTE:
			*v = uint(C.pn_data_get_ubyte(data))
		case C.PN_USHORT:
			*v = uint(C.pn_data_get_ushort(data))
		case C.PN_UINT:
			*v = uint(C.pn_data_get_uint(data))
		case C.PN_ULONG:
			if intIs64 {
				*v = uint(C.pn_data_get_ulong(data))
			} else {
				doPanic(data, v)
			}
		default:
			doPanic(data, v)
		}

	case *float32:
		panicUnless(pnType == C.PN_FLOAT, data, v)
		*v = float32(C.pn_data_get_float(data))

	case *float64:
		switch pnType {
		case C.PN_FLOAT:
			*v = float64(C.pn_data_get_float(data))
		case C.PN_DOUBLE:
			*v = float64(C.pn_data_get_double(data))
		default:
			doPanic(data, v)
		}

	case *string:
		switch pnType {
		case C.PN_STRING:
			*v = goString(C.pn_data_get_string(data))
		case C.PN_SYMBOL:
			*v = goString(C.pn_data_get_symbol(data))
		case C.PN_BINARY:
			*v = goString(C.pn_data_get_binary(data))
		default:
			doPanic(data, v)
		}

	case *[]byte:
		switch pnType {
		case C.PN_STRING:
			*v = goBytes(C.pn_data_get_string(data))
		case C.PN_SYMBOL:
			*v = goBytes(C.pn_data_get_symbol(data))
		case C.PN_BINARY:
			*v = goBytes(C.pn_data_get_binary(data))
		default:
			doPanic(data, v)
		}
		return

	case *Char:
		panicUnless(pnType == C.PN_CHAR, data, v)
		*v = Char(C.pn_data_get_char(data))

	case *Binary:
		panicUnless(pnType == C.PN_BINARY, data, v)
		*v = Binary(goBytes(C.pn_data_get_binary(data)))

	case *Symbol:
		panicUnless(pnType == C.PN_SYMBOL, data, v)
		*v = Symbol(goBytes(C.pn_data_get_symbol(data)))

	case *time.Time:
		panicUnless(pnType == C.PN_TIMESTAMP, data, v)
		*v = goTime(C.pn_data_get_timestamp(data))

	case *UUID:
		panicUnless(pnType == C.PN_UUID, data, v)
		pn := C.pn_data_get_uuid(data)
		copy((*v)[:], C.GoBytes(unsafe.Pointer(&pn.bytes), 16))

	case *AnnotationKey:
		panicUnless(pnType == C.PN_ULONG || pnType == C.PN_SYMBOL || pnType == C.PN_STRING, data, v)
		unmarshal(&v.value, data)

	case *AnyMap:
		panicUnless(C.pn_data_type(data) == C.PN_MAP, data, v)
		n := int(C.pn_data_get_map(data)) / 2
		if cap(*v) < n {
			*v = make(AnyMap, n)
		}
		*v = (*v)[:n]
		enter(data, *v)
		defer exit(data, *v)
		for i := 0; i < n; i++ {
			next(data, *v)
			unmarshal(&(*v)[i].Key, data)
			next(data, *v)
			unmarshal(&(*v)[i].Value, data)
		}

	case *interface{}:
		getInterface(data, v)

	default: // This is not one of the fixed well-known types, reflect for map and slice types

		switch rt.Elem().Kind() {
		case reflect.Map:
			getMap(data, v)
		case reflect.Slice:
			getSequence(data, v)
		default:
			doPanic(data, v)
		}
	}
}