Convert c struct with macro to zig

I know zig is not support macro.
But in c language, often use macro in struct (eg.RFC protocol).
I want to find a more zig-native way convert to zig.

for sample:

c code to define rtp header( rtp is an rfc protocol):

typedef struct {
#if RTP_BIG_ENDIAN
    unsigned int version:2;   /* protocol version */
    unsigned int p:1;         /* padding flag */
    unsigned int x:1;         /* header extension flag */
    unsigned int cc:4;        /* CSRC count */
    unsigned int m:1;         /* marker bit */
    unsigned int pt:7;        /* payload type */
#else
    unsigned int cc:4;        /* CSRC count */
    unsigned int x:1;         /* header extension flag */
    unsigned int p:1;         /* padding flag */
    unsigned int version:2;   /* protocol version */
    unsigned int pt:7;        /* payload type */
    unsigned int m:1;         /* marker bit */
#endif
    unsigned int seq:16;      /* sequence number */
    uint32_t ts;               /* timestamp */
    uint32_t ssrc;             /* synchronization source */
    uint32_t csrc[1];          /* optional CSRC list */
} rtp_hdr_t;

Is there a ‘standard’ way convert it to zig code?

Unfortunately zig translate-c does not translate structs with bit-fields and uses opaque instead.

One way to do it is with packed struct. Packed structs retain fields order, have no padding, and bits are least to most significant.

const RtpHdr = packed struct {
    version: u2,
    p: u1,
    ...
    seq: u16,
    ts: u32,
    ...
};

Zig supports arbitrary bit-width integers, referenced by using an identifier of i or u followed by digits. For example, the identifier u3 refers to an unsigned 3-bit integer. The maximum allowed bit-width of an integer type is 65535

To handle endian:

const builtin = @import("builtin");
const native_endian = builtin.cpu.arch.endian();
const RtpHdr = if (native_endian == std.builtin.Endian.big) packed struct {
    ...
} else packed struct {
    ...
};
2 Likes

Thanks very much!