file-handling · intermediate · ~15 min

Binary Struct File Serializer

Serialize and deserialize C structures with explicit endianness and fixed wire layouts.

Challenge

Binary serialization writes memory structures directly into deterministic byte streams. Serializing integer fields in big-endian network byte order ensures cross-platform compatibility.

Your Task

Given the record definition:

typedef struct {
    uint32_t record_id;
    uint16_t score;
    uint8_t flags;
    char name[16];
} StudentRecord;

Implement serialization and deserialization into a fixed 23-byte wire buffer:

int serialize_record(const StudentRecord *rec, uint8_t *wire, size_t wire_cap);
int deserialize_record(StudentRecord *rec, const uint8_t *wire, size_t wire_len);

Wire Format (23 bytes total)

  • Offset 0..3: record_id (32-bit big endian)
  • Offset 4..5: score (16-bit big endian)
  • Offset 6: flags (8-bit)
  • Offset 7..22: name (16 bytes, NUL-padded)

Rules

  1. In serialize_record: if rec == NULL, wire == NULL, or wire_cap < 23, return -1. Write the 23 bytes and return 23.
  2. In deserialize_record: if rec == NULL, wire == NULL, or wire_len < 23, return -1. Decode fields, ensure rec->name is NUL-terminated, and return 0.

Example

StudentRecord s = { .record_id = 1001, .score = 95, .flags = 0x01, .name = "Alice" };
uint8_t buf[32];
serialize_record(&s, buf, sizeof(buf)); // returns 23
StudentRecord out;
deserialize_record(&out, buf, 23); // returns 0, out.record_id == 1001

Input format

rec: StudentRecord pointer; wire: byte buffer; capacities: size_t.

Output format

Returns 23 on serialization, 0 on deserialization, -1 on error.

Constraints

Big-endian integer encoding. Exact 23-byte wire layout.

Starter code

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

typedef struct {
    uint32_t record_id;
    uint16_t score;
    uint8_t flags;
    char name[16];
} StudentRecord;

int serialize_record(const StudentRecord *rec, uint8_t *wire, size_t wire_cap) {
    (void)rec; (void)wire; (void)wire_cap;
    return -1;
}
int deserialize_record(StudentRecord *rec, const uint8_t *wire, size_t wire_len) {
    (void)rec; (void)wire; (void)wire_len;
    return -1;
}

Common mistakes

Relying on raw memcpy of struct (subject to compiler padding and endian bugs).

Edge cases to handle

Buffer shorter than 23 bytes returns -1; name field without internal NUL is capped with NUL at index 15.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.