#ifndef _NETUTIL_TYPES_H_
#define _NETUTIL_TYPES_H_

#include <stdint.h>
#include <stddef.h>

struct uint16_net {
    uint8_t val[2];
} __attribute__((__packed__));

static inline struct uint16_net uint16_wr(uint16_t val)
{
    return (struct uint16_net){{
        (val >> 8) & 0xff,
        val & 0xff
    }};
}

static inline uint16_t uint16_rd(struct uint16_net val_net)
{
    return (
        ((uint16_t)val_net.val[0] << 8) |
        (uint16_t)val_net.val[1]
    );
}

struct uint32_net {
    uint8_t val[4];
} __attribute__((__packed__));

static inline struct uint32_net uint32_wr(uint32_t val)
{
    return (struct uint32_net){{
        (val >> 24) & 0xff,
        (val >> 16) & 0xff,
        (val >> 8) & 0xff,
        val & 0xff
    }};
}

static inline uint32_t uint32_rd(struct uint32_net val_net)
{
    return (
        ((uint32_t)val_net.val[0] << 24) |
        ((uint32_t)val_net.val[1] << 16) |
        ((uint32_t)val_net.val[2] << 8) |
        (uint32_t)val_net.val[3]
    );
}

struct eth_addr_net {
    uint8_t addr[6];
} __attribute__((__packed__));

static inline struct eth_addr_net eth_addr_wr(uint64_t addr)
{
    return (struct eth_addr_net){{
        (addr >> 40) & 0xff,
        (addr >> 32) & 0xff,
        (addr >> 24) & 0xff,
        (addr >> 16) & 0xff,
        (addr >> 8) & 0xff,
        addr & 0xff
    }};
}

static inline uint64_t eth_addr_rd(struct eth_addr_net addr_net)
{
    return (
        ((uint64_t)addr_net.addr[0] << 40) |
        ((uint64_t)addr_net.addr[1] << 32) |
        ((uint64_t)addr_net.addr[2] << 24) |
        ((uint64_t)addr_net.addr[3] << 16) |
        ((uint64_t)addr_net.addr[4] << 8) |
        (uint64_t)addr_net.addr[5]
    );
}

typedef uint32_t ip_addr_t;
typedef struct uint32_net ip_addr_net_t;

#endif
