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

时间:2022-08-26 15:24:40

I'm reading a binary file, and within it there is a structure where the first byte of data indicates the type of data following it. I'm trying to handle this via pattern matching, and am having trouble.

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

I've tried a few ways I figured may work, none of which do. You can see my feeble attempts below:

我尝试了一些我认为可行的方法,但没有一种方法可行。您可以在下面看到我的微弱尝试:

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!"]

I'd like to get: ["11!", "12!", "13!"] instead.

我想得到:[“11!”,“12!”,“13!”]。

The data matched by these is all a fixed size (in this case 5 total bytes). This SO question seems to suggest I need to specify the total size as well? Not sure how to do that.

这些匹配的数据都是固定大小(在这种情况下总共5个字节)。这个SO问题似乎表明我还需要指定总大小?不知道该怎么做。

Ultimately I don't care about the value of the first byte if the methods are dispatched via matching, so rest is the only thing I really need within each method body. What am I missing?

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

1 个解决方案

#1


Each unbound variable in a binary pattern matches one byte by default. If you want to match an arbitrary length rest, you need to use the binary modifier.

默认情况下,二进制模式中的每个未绑定变量都匹配一个字节。如果要匹配任意长度的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

#1


Each unbound variable in a binary pattern matches one byte by default. If you want to match an arbitrary length rest, you need to use the binary modifier.

默认情况下,二进制模式中的每个未绑定变量都匹配一个字节。如果要匹配任意长度的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