API Design

1

Library API Design, First Layer

5 minute

In C library APIs, one pointer can mean many different things:

int parse_packet(const uint8_t *data, size_t len, struct Packet *out);
void normalize(uint8_t *data, size_t len);
void consume_buffer(uint8_t *data, size_t len);
uint8_t *make_packet(size_t *out_len);

These signatures all involve pointers, but the API meaning differs:

  • read-only input
  • in-place mutation
  • output result
  • taking over a caller-owned resource
  • creating a new resource for the caller

The first layer of Rust API design is making those intentions visible in the type.

Read-Only Input: Borrow

C read-only buffer:

uint32_t checksum(const uint8_t *data, size_t len);

Rust uses a slice:

fn checksum(data: &[u8]) -> u32 {
    data.iter().map(|b| *b as u32).sum()
}

&[u8] means the function temporarily reads bytes. It does not own the memory and cannot mutate it.

Read More