Binaries & the Bit Syntax

Erlang's bit syntax makes binary protocol parsing remarkably concise.

15.1 Constructing

<<1, 2, 3>>,
<<"abc">>,
<<255:16>>,                      % <<0,255>> — 16-bit big-endian
<<1:1, 0:1, 1:6>>,               % bits
<<3.14:64/float>>,
<<42:32/little-unsigned-integer>>,
<<"héllo"/utf8>>,
X = 300, <<X:16/big>>.

15.2 Segment syntax

Type: integer (default), float, binary/bytes, bitstring/bits, utf8, utf16, utf32

Signedness: signed, unsigned (default) Endianness: big (default), little, native Unit: unit:N (size multiplier)

15.3 Pattern matching

<<A, B, Rest/binary>> = <<1, 2, 3, 4>>,                % A=1, B=2, Rest = <<3,4>>
<<Len:16, Payload:Len/binary, Tail/binary>> = Packet,
<<R:5, G:6, B:5>> = <<Color:16>>.                     % RGB565

%% IPv4 header
parse_ip(<<4:4, IHL:4, _TOS:8, TotalLen:16,
           _Id:16, _Flags:3, _FragOff:13,
           TTL:8, Proto:8, _Checksum:16,
           Src:4/binary, Dst:4/binary, _/binary>>) ->
    #{ihl => IHL, len => TotalLen, ttl => TTL, proto => Proto,
      src => list_to_tuple(binary_to_list(Src)), dst => list_to_tuple(binary_to_list(Dst))}.

15.4 The binary module

byte_size(<<"abc">>), bit_size(<<1:3>>),
binary:part(<<"hello">>, 1, 3),             % <<"ell">>
binary:split(<<"a,b,c">>, <<",">>, [global]),
binary:replace(<<"aXbX">>, <<"X">>, <<"-">>, [global]),
binary:match(<<"hello">>, <<"ll">>),        % {2,2}
binary:matches(<<"abab">>, <<"b">>),
binary:copy(<<"x">>, 3),                    % <<"xxx">>
binary:copy(SubBin),                        % detach from large parent binary
binary:encode_hex(<<255>>), binary:decode_hex(<<"FF">>),   % OTP 24+
binary:first(<<"abc">>), binary:last(<<"abc">>),
binary:bin_to_list(<<"abc">>),
base64:encode(<<"hello">>), base64:decode(<<"aGVsbG8=">>).

15.5 Term serialization

Bin = term_to_binary(#{a => [1, 2]}),
binary_to_term(Bin),
binary_to_term(Untrusted, [safe]).          % refuse new atoms/funs from untrusted data

15.6 Binary memory model

Heap binaries (≤ 64 bytes) live on the process heap and are copied.

Refc binaries (> 64 bytes) live off-heap, reference-counted, shared between processes.

Sub-binaries reference part of a binary — beware keeping huge binaries alive; use binary:copy/1.

Appending to a binary in a loop is optimised by the runtime (writable binaries).