Add serial module — little-endian binary serialization primitives

put_u8/16/32/64 and get_u8/16/32/64 (plus signed variants) for packing
and unpacking values at explicit byte offsets in a buffer. Each value is
encoded byte-by-byte with explicit shift operations — no struct casting,
no alignment assumptions, correct on any host endianness.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-25 22:15:41 +00:00
parent e1b848333b
commit b56dfae672
3 changed files with 141 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
ROOT := $(abspath ../../..)
include $(ROOT)/common.mk
MODULE_BUILD = $(BUILD)/serial
.PHONY: all clean
all: $(MODULE_BUILD)/serial.o
$(MODULE_BUILD)/serial.o: serial.c $(ROOT)/include/serial.h | $(MODULE_BUILD)
$(CC) $(CFLAGS) -c -o $@ $<
$(MODULE_BUILD):
mkdir -p $@
clean:
rm -f $(MODULE_BUILD)/serial.o

View File

@@ -0,0 +1,92 @@
#include <stdint.h>
#include "serial.h"
/* -- put -- */
void put_u8(uint8_t *buf, uint32_t offset, uint8_t value) {
buf[offset] = value;
}
void put_u16(uint8_t *buf, uint32_t offset, uint16_t value) {
buf[offset + 0] = (uint8_t)(value);
buf[offset + 1] = (uint8_t)(value >> 8);
}
void put_u32(uint8_t *buf, uint32_t offset, uint32_t value) {
buf[offset + 0] = (uint8_t)(value);
buf[offset + 1] = (uint8_t)(value >> 8);
buf[offset + 2] = (uint8_t)(value >> 16);
buf[offset + 3] = (uint8_t)(value >> 24);
}
void put_u64(uint8_t *buf, uint32_t offset, uint64_t value) {
buf[offset + 0] = (uint8_t)(value);
buf[offset + 1] = (uint8_t)(value >> 8);
buf[offset + 2] = (uint8_t)(value >> 16);
buf[offset + 3] = (uint8_t)(value >> 24);
buf[offset + 4] = (uint8_t)(value >> 32);
buf[offset + 5] = (uint8_t)(value >> 40);
buf[offset + 6] = (uint8_t)(value >> 48);
buf[offset + 7] = (uint8_t)(value >> 56);
}
void put_i8(uint8_t *buf, uint32_t offset, int8_t value) {
put_u8(buf, offset, (uint8_t)value);
}
void put_i16(uint8_t *buf, uint32_t offset, int16_t value) {
put_u16(buf, offset, (uint16_t)value);
}
void put_i32(uint8_t *buf, uint32_t offset, int32_t value) {
put_u32(buf, offset, (uint32_t)value);
}
void put_i64(uint8_t *buf, uint32_t offset, int64_t value) {
put_u64(buf, offset, (uint64_t)value);
}
/* -- get -- */
uint8_t get_u8(const uint8_t *buf, uint32_t offset) {
return buf[offset];
}
uint16_t get_u16(const uint8_t *buf, uint32_t offset) {
return (uint16_t)buf[offset + 0]
| ((uint16_t)buf[offset + 1] << 8);
}
uint32_t get_u32(const uint8_t *buf, uint32_t offset) {
return (uint32_t)buf[offset + 0]
| ((uint32_t)buf[offset + 1] << 8)
| ((uint32_t)buf[offset + 2] << 16)
| ((uint32_t)buf[offset + 3] << 24);
}
uint64_t get_u64(const uint8_t *buf, uint32_t offset) {
return (uint64_t)buf[offset + 0]
| ((uint64_t)buf[offset + 1] << 8)
| ((uint64_t)buf[offset + 2] << 16)
| ((uint64_t)buf[offset + 3] << 24)
| ((uint64_t)buf[offset + 4] << 32)
| ((uint64_t)buf[offset + 5] << 40)
| ((uint64_t)buf[offset + 6] << 48)
| ((uint64_t)buf[offset + 7] << 56);
}
int8_t get_i8(const uint8_t *buf, uint32_t offset) {
return (int8_t)get_u8(buf, offset);
}
int16_t get_i16(const uint8_t *buf, uint32_t offset) {
return (int16_t)get_u16(buf, offset);
}
int32_t get_i32(const uint8_t *buf, uint32_t offset) {
return (int32_t)get_u32(buf, offset);
}
int64_t get_i64(const uint8_t *buf, uint32_t offset) {
return (int64_t)get_u64(buf, offset);
}