Tincture.Font.Binary (Tincture v0.1.0)

Copy Markdown View Source

Bounds-checked readers for big-endian font table data.

Every sfnt-based format — TrueType, OpenType, CFF — stores its tables as big-endian integers at offsets that the file itself supplies. Those offsets are untrusted: a malformed or hostile font can point anywhere. These readers return :error (or nil, for the read_bytes/3 shape) rather than raising, so a bad offset degrades one table instead of crashing the render.

They were previously private to Tincture.Font.TTF, which meant every table parser had to live in the same module to reach them.

Summary

Functions

Read len bytes at offset, or nil if the range does not fit.

Read a signed 16-bit big-endian integer at offset.

Decode a whole binary as a list of signed 16-bit big-endian integers.

Read length bytes at offset, or :error if that range is not fully inside data.

Read an unsigned 16-bit big-endian integer at offset.

Decode a whole binary as a list of unsigned 16-bit big-endian integers.

Read an unsigned 32-bit big-endian integer at offset.

Decode a whole binary as a list of unsigned 32-bit big-endian integers.

Functions

bytes(data, offset, len)

@spec bytes(binary(), non_neg_integer(), pos_integer()) :: binary() | nil

Read len bytes at offset, or nil if the range does not fit.

Returns nil rather than :error because its callers thread the result straight into pattern matches where a nil is the natural "absent" case.

s16(data, offset)

@spec s16(binary(), non_neg_integer()) :: {:ok, integer()} | :error

Read a signed 16-bit big-endian integer at offset.

s16_list(bin)

@spec s16_list(binary()) :: [integer()]

Decode a whole binary as a list of signed 16-bit big-endian integers.

slice(data, offset, length)

@spec slice(binary(), non_neg_integer(), non_neg_integer()) ::
  {:ok, binary()} | :error

Read length bytes at offset, or :error if that range is not fully inside data.

u16(data, offset)

@spec u16(binary(), non_neg_integer()) :: {:ok, non_neg_integer()} | :error

Read an unsigned 16-bit big-endian integer at offset.

u16_list(bin)

@spec u16_list(binary()) :: [non_neg_integer()]

Decode a whole binary as a list of unsigned 16-bit big-endian integers.

Deliberately has no clause for a trailing odd byte: callers slice exactly count * 2 bytes, so an odd length means the slice was computed wrongly and should surface rather than silently truncate. Preserved from the original implementation; changing it is a behaviour decision, not a refactor.

u32(data, offset)

@spec u32(binary(), non_neg_integer()) :: {:ok, non_neg_integer()} | :error

Read an unsigned 32-bit big-endian integer at offset.

u32_list(bin)

@spec u32_list(binary()) :: [non_neg_integer()]

Decode a whole binary as a list of unsigned 32-bit big-endian integers.