func marshal()

in go/pkg/amqp/marshal.go [170:295]


func marshal(i interface{}, data *C.pn_data_t) {
	switch v := i.(type) {
	case nil:
		C.pn_data_put_null(data)
	case bool:
		C.pn_data_put_bool(data, C.bool(v))

	// Signed integers
	case int8:
		C.pn_data_put_byte(data, C.int8_t(v))
	case int16:
		C.pn_data_put_short(data, C.int16_t(v))
	case int32:
		C.pn_data_put_int(data, C.int32_t(v))
	case int64:
		C.pn_data_put_long(data, C.int64_t(v))
	case int:
		if intIs64 {
			C.pn_data_put_long(data, C.int64_t(v))
		} else {
			C.pn_data_put_int(data, C.int32_t(v))
		}

		// Unsigned integers
	case uint8:
		C.pn_data_put_ubyte(data, C.uint8_t(v))
	case uint16:
		C.pn_data_put_ushort(data, C.uint16_t(v))
	case uint32:
		C.pn_data_put_uint(data, C.uint32_t(v))
	case uint64:
		C.pn_data_put_ulong(data, C.uint64_t(v))
	case uint:
		if intIs64 {
			C.pn_data_put_ulong(data, C.uint64_t(v))
		} else {
			C.pn_data_put_uint(data, C.uint32_t(v))
		}

		// Floating point
	case float32:
		C.pn_data_put_float(data, C.float(v))
	case float64:
		C.pn_data_put_double(data, C.double(v))

		// String-like (string, binary, symbol)
	case string:
		C.pn_data_put_string(data, pnBytes([]byte(v)))
	case []byte:
		C.pn_data_put_binary(data, pnBytes(v))
	case Binary:
		C.pn_data_put_binary(data, pnBytes([]byte(v)))
	case Symbol:
		C.pn_data_put_symbol(data, pnBytes([]byte(v)))

		// Other simple types
	case time.Time:
		C.pn_data_put_timestamp(data, pnTime(v))
	case UUID:
		C.pn_data_put_uuid(data, *(*C.pn_uuid_t)(unsafe.Pointer(&v[0])))
	case Char:
		C.pn_data_put_char(data, (C.pn_char_t)(v))

		// Described types
	case Described:
		C.pn_data_put_described(data)
		C.pn_data_enter(data)
		marshal(v.Descriptor, data)
		marshal(v.Value, data)
		C.pn_data_exit(data)

		// Restricted type annotation-key, marshals as contained value
	case AnnotationKey:
		marshal(v.Get(), data)

		// Special type to represent AMQP maps with keys that are illegal in Go
	case AnyMap:
		C.pn_data_put_map(data)
		C.pn_data_enter(data)
		defer C.pn_data_exit(data)
		for _, kv := range v {
			marshal(kv.Key, data)
			marshal(kv.Value, data)
		}

	default:
		// Examine complex types (Go map, slice, array) by reflected structure
		switch reflect.TypeOf(i).Kind() {

		case reflect.Map:
			m := reflect.ValueOf(v)
			C.pn_data_put_map(data)
			if C.pn_data_enter(data) {
				defer C.pn_data_exit(data)
			} else {
				panic(dataMarshalError(i, data))
			}
			for _, key := range m.MapKeys() {
				marshal(key.Interface(), data)
				marshal(m.MapIndex(key).Interface(), data)
			}

		case reflect.Slice, reflect.Array:
			// Note: Go array and slice are mapped the same way:
			// if element type is an interface, map to AMQP list (mixed type)
			// if element type is a non-interface type map to AMQP array (single type)
			s := reflect.ValueOf(v)
			if pnType, ok := arrayTypeMap[s.Type().Elem()]; ok {
				C.pn_data_put_array(data, false, pnType)
			} else {
				C.pn_data_put_list(data)
			}
			C.pn_data_enter(data)
			defer C.pn_data_exit(data)
			for j := 0; j < s.Len(); j++ {
				marshal(s.Index(j).Interface(), data)
			}

		default:
			panic(newMarshalError(v, "no conversion"))
		}
	}
	if err := dataMarshalError(i, data); err != nil {
		panic(err)
	}
}