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)
}
}