Erlangのバイナリは一つの要素が255を越えると切断とされます。つまり8bitしか取らない。
11> Bin11 = <<1, 255>>.
<<1,255>>
12> erlang:binary_to_list(Bin11).
[1,255]
13> f().
ok
14> Bin11 = <<1, 256>>.
<<1,0>>
15> erlang:binary_to_list(Bin11).
[1,0]
Cは256で16 bitで表示するとして、Bin22は4 byteになります。結局Cは1 byteずつリストの中に表示されます。
17> A=1, B = 17, C=256.
256
21> Bin22= <<A, B, C:16>>.
<<1,17,1,0>>
22> erlang:binary_to_list(Bin22).
[1,17,1,0]
A:8
の後ろに/binary
つけると8の意味も変わって、ビットからバイトに変わりました。
18> <<A:8, Rest/binary>> = <<1,2,3,4,5,6,7,8,9>>.
<<1,2,3,4,5,6,7,8,9>>
19> A.
1
20> f().
ok
21> <<A:8/binary,Rest/binary>> = <<1,2,3,4,5,6,7,8,9>>.
<<1,2,3,4,5,6,7,8,9>>
22> A.
<<1,2,3,4,5,6,7,8>>
Elixirの中にBinaryのList Comprehension
8ビットずつ取ってくるか、16ビットずつ取ってくるかによって、結果も違ってきます。
iex(16)> a = for <<b :: 16 <- <<0, 1, 0, 2, 0, 3>> >>, do: b
[1, 2, 3]
iex(17)> a = for <<b :: 8 <- <<0, 1, 0, 2, 0, 3>> >>, do: b
[0, 1, 0, 2, 0, 3]
binは3ビットを指定して、:erlang.binary_to_list
で変換しようとすると失敗します。8ビットの倍数じゃないとダメみたいです。
iex(20)> bin = <<1::size(3)>>
<<1::size(3)>>
iex(21)> :erlang.binary_to_list(bin)
** (ArgumentError) argument error
:erlang.binary_to_list(<<1::size(3)>>)
iex(21)> bin = <<1::size(8)>>
<<1>>
iex(22)> :erlang.binary_to_list(bin)
[1]
bitstringの場合, <<1,2,3>>
は下のようになっています。header
は最初の3ビットで0
になります。そして8ビットずつ取っていくので、最後に5ビットが残ります。
0000 0001 0000 0010 0000 0010
iex(26)> << header :: size(3), data :: bitstring >> = <<1,2,3>>
<<1, 2, 3>>
iex(27)> header
0
iex(28)> data
<<8, 16, 3::size(5)>>
Elixirの中にまた別のバイナリサイズ(バイト長)の定義方法は、<<header :: binary - size(1), data :: binary>>
で、ここでのbinary - size(1)
は1バイト長(つまり8ビット)を意味します。
iex(29)> << header :: binary - size(1), data :: binary >> = <<1,2,3>>
<<1, 2, 3>>
iex(30)> header
<<1>>
iex(31)> data
<<2, 3>>
iex(32)> << header :: binary - size(2), data :: binary >> = <<1,2,3>>
<<1, 2, 3>>
iex(33)> header
<<1, 2>>
iex(34)> data
<<3>>
上のElixir 中のbinary - size(length)
に比べてErlangの書き方は下にあります。Part:1/binary
中の1は1バイトという意味です。
1> <<Part:1/binary, Rest/binary>> = <<1,2,3>>.
<<1,2,3>>
2> Part.
<<1>>
4> f().
ok
5> <<Part:2/binary, Rest/binary>> = <<1,2,3>>.
<<1,2,3>>
6> Part.
<<1,2>>