[erlang-questions] bit syntax: 0-sized segments

Kostis Sagonas kostis@REDACTED
Fri Mar 8 01:09:20 CET 2013

On 03/08/2013 12:09 AM, Richard A. O'Keefe wrote:
> Surely zero-length segments *have* to be allowed?
> Suppose you have
>     <<N:16, B:N/bytes, R/binary>>  = Whatever
> Is this supposed to crash if N = 0?
> Why?
> I cannot understand what is supposed to be 'weird' about
> zero-length segments.

Perhaps the exact issue that I find slightly "weird" was too subtle in 
my mail.

First of all, note that all your examples involve binary segments. In 
this case (and in bitstrings, which is its generalization) one could 
argue that there is a perfectly sensible "solution" to the matching 
problem, namely the empty bitstring as can be seen below.

9> <<X:0/binary>> = <<>>.
10> X.

IMO, the solution to the previous matching makes sense because binaries 
(bitstrings) get "flattened" out when nested in other ones: for any 
binary (bitstring) B, the binary (bitstring) <<B/bits>> is the same as 
B.  Also, for all bitstrings B the following matching succeeds and 
returns X = B.

   B = <<...SOME BITSTRING...>, N = bit_size(B), <<X:N/bitstring>> = B.

Note that B = <<>> and <<X:0/binary>> is just a special case of the 
above matching.

So far so good.

When one moves to integer segments the above property does not make much 
sense anymore (esp. since bit_size is not defined for anything other 
than bitstrings). In particular, the current implementation of binary 
pattern matching has chosen to return an "arbitrary" integer, namely 0, 
as the result. I can may well see that many would consider the following 
binding for X to 0 a bit weird.

1> <<X:0/integer>> = <<42:0>>.
2> X.

Moreover, the situation is arguably even more weird for floats:

3> <<F:0/float>> = <<42:0>>.
4> F.

especially so since one cannot even write something like <<42:0/float>> 
(or even <<3.1415:0/float>>) as a construction.

I am not so convinced that pattern matching with 0-size segments make 
sense for types other than bitstrings (binaries).


> Look at example 4 from the Bit Syntax documentation:
> -define(IP_VERSION, 4).
> -define(IP_MIN_HDR_LEN, 5).
> DgramSize = byte_size(Dgram),
> case Dgram of
>      <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
>        ID:16, Flgs:3, FragOff:13,
>        TTL:8, Proto:8, HdrChkSum:16,
>        SrcIP:32,
>        DestIP:32, RestDgram/binary>>  when HLen>=5, 4*HLen=<DgramSize ->
>          OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
>          <<Opts:OptsLen/binary,Data/binary>>  = RestDgram,
>      ...
> end.
> If there are no options, so that HLen == IP_MIN_HDR_LEN and OptsLen == 0,
> this reduces to
> 	<<Opts:0/binary,Data/binary>>  = RestDgram.
> Is there anything "weird" about a datagram with no options?
> If the issue is construction rather than matching,
> is there anything "weird" about constructing a datagram with no options?
> Zero is a perfectly good size.  It would be a serious defect in Erlang
> if it _didn't_ allow zero-size segments.  ....

More information about the erlang-questions mailing list