匹配方法签名中的二进制文件的一部分

Matching on part of a binary in a method signature

我正在读取一个二进制文件,其中有一个结构,其中数据的第一个字节指示其后的数据类型。我正在尝试通过模式匹配来处理这个问题,但遇到了麻烦。

我尝试了几种我认为可行的方法,none 其中可行。您可以在下面看到我的微弱尝试:

defmodule Test do

  def build(<< 0x11, rest >>) do
    "11!"
  end

  def build(<< 0x12, rest :: size(4) >>) do
    "12!"
  end

  def build(<< type, rest >>)
  when type == 0x13 do
    "13!"
  end

  def build(bytes) do
    "Unknown!"
  end

end

[ << 0x11, 0x01, 0x02, 0x03, 0x04 >>,
  << 0x12, 0x01, 0x02, 0x03, 0x04 >>,
  << 0x13, 0x01, 0x02, 0x03, 0x04 >> ]
|> Enum.map(&Test.build/1)
|> IO.inspect
# => ["Unknown!", "Unknown!", "Unknown!"]

我想得到:["11!", "12!", "13!"]

这些匹配的数据都是固定大小的(在本例中为5个字节)。 This SO question 似乎建议我也需要指定总大小?不知道该怎么做。

最终,如果方法是通过匹配分派的,我不关心第一个字节的值,所以 rest 是每个方法主体中我真正需要的唯一东西。我错过了什么?

二进制模式中的每个未绑定变量默认匹配一个字节。如果要匹配任意长度的休止符,需要使用binary修饰符。

defmodule Test do
  def build(<<0x11, rest :: binary>>) do
    "11!"
  end

  def build(<<0x12, rest :: binary>>) do
    "12!"
  end

  def build(<<0x13, rest :: binary>>) do
    "13!"
  end

  def build(bytes) do
    "Unknown!"
  end
end