Elixir二进制匹配组合'字节' &安培; '整数'

时间:2018-02-24 22:34:35

标签: parsing pattern-matching elixir

问题

我想制作一个用Elixir编写的自定义文件打包器但是我遇到了问题。 我必须匹配一个以字节为单位的数字。例如:

iex(1)> << value :: little-???-size(4), _ :: binary >> = << 1, 0, 0, 0, 255 >>
<< 1, 0, 0, 0, 255 >>
iex(2)> value
1

我知道我可以使用little-size(32),但大小是以位为单位。我可以使用bytes-size(4),但我得<< 1, 0, 0, 0 >>。也许有任何方法可以将它们结合起来吗?

文件

我的文件遵循以下语法:

> 4 bytes: number of files

// First file
> 4 bytes: sub-file's name length
> X bytes: sub-file's name
> 4 bytes: sub-file's content length
> X bytes: sub-file's content

// Second file
> 4 bytes: sub-file's name length
> ...

目标

我只想将以下代码合并到只匹配一个模式

# Get name length
<<
    name_length :: bytes-size(4),
    rest :: binary
>> = data

name_bytes = name_length * 8

# Get Filename, and buffer size
<<
    filename :: size(name_bytes),
    buffer_size :: bytes-size(4),
    rest :: binary
>> = rest

buffer_bytes = buffer_size * 8

# Get buffer
<<
    buffer :: size(buffer_bytes),
    rest :: binary
>> = rest

1 个答案:

答案 0 :(得分:0)

我刚刚找到答案。如果有些人遇到与我相同的问题,请使用binary-size(size_in_byte)(有关二进制类型的更多信息,只需将h <<>>放入iex控制台)。

实施例

iex(1)> <<
...         name_length :: little-size(32),
...         filename :: binary-size(name_length),
...         buffer_size :: little-size(32),
...         buffer :: binary-size(buffer_size),
...         rest :: binary
...     >> = data
[ ... some data ... ]
iex(2)> name_length
8
iex(3)> filename
"Toto.txt"

说明:

来自iex doc:

[...]

### Unit and Size

The length of the match is equal to the `unit` (a number of bits) times the `size` (the number of repeated segments of length `unit`).

Type      | Default Unit
--------- | ------------
`integer` | 1 bit
`float`   | 1 bit
`binary`  | 8 bits

[...]

For binaries, the default is the size of the binary. Only the last binary in a match can use the default size. All others must have their size specified explicitly, even if the match is unambiguous. For example:

iex> <<name::binary-size(5), " the ", species::binary>> = <<"Frank the Walrus">>
"Frank the Walrus"
iex> {name, species}
{"Frank", "Walrus"}