Erlang 在elixir二进制文件中匹配多个部分以解析HTTP/2.0帧

Erlang 在elixir二进制文件中匹配多个部分以解析HTTP/2.0帧,erlang,pattern-matching,elixir,binary-data,Erlang,Pattern Matching,Elixir,Binary Data,我发现了一种从二进制匹配帧的快速方法。 长度匹配为整数,c部分(有效负载)的八位字节数与长度字段中声明的八位字节数相同。(前三个八位组) rest=buffer 问题是要达到我的框架,我需要重新组合部件 frame = <<length::24, b::48, c::binary>> frame= 是否仍要在原始匹配中指定帧变量。类似下面的内容。虽然这个精确的版本不起作用 (frame=)rest=缓冲区 Edit或类似以下的语法也有意义 << fra

我发现了一种从二进制匹配帧的快速方法。 长度匹配为整数,c部分(有效负载)的八位字节数与长度字段中声明的八位字节数相同。(前三个八位组)

rest=buffer
问题是要达到我的框架,我需要重新组合部件

frame = <<length::24, b::48, c::binary>>
frame=
是否仍要在原始匹配中指定帧变量。类似下面的内容。虽然这个精确的版本不起作用

(frame=)rest=缓冲区
Edit或类似以下的语法也有意义

<< frame = <<length::24, _::48, _::binary-size(length)>>, rest::binary>>
>

好的,这样做是不可能的,但您可以声明一个方便的助手,以避免重复键入:

def matcher(buffer)
  with <<length::24, b::48, c::binary-size(length), rest::binary>> <- buffer do 
    {:ok, <<length::24, b::48, c::binary-size(length)>>, rest}
  else
    other -> {:error, other}
  end
end

我不太明白
b::48
到底代表了标题的哪一部分

<> P>但无论如何,明智的做法是考虑两件事。

  • 返回帧二进制文件并不是在执行。如果您已经解析了帧,并且知道它是完整的,那么将其作为
    etf
    表示返回。不要再重新分析它
  • 一句话不一定更有效。这一切都是关于以某种方式组合和提取二进制部分
  • 函数定义中的模式匹配也非常有效,请尽可能针对不同的代码路径进行匹配
  • 我不知道性能到底有多好。我认为这只是一种速记,但它的性能可能足够好,即使它不同

    这段代码应该创建并链接二进制部分,而不应该创建任何新的二进制文件。因此,它实际上相当有效

    =缓冲区
    帧=
    

    如果您想了解我是如何处理此类数据的,请看一看。

    谢谢,我不想让人觉得我忘恩负义,但我已经做到了:-)。我想知道一行是否可能,因为它可能更有效。不创建和连接临时二进制文件您可能已经知道这一点,但为了避免重新创建二进制文件,您可以使用
    :binary.part(buffer,0,3+6+长度)
    <代码>:二进制。第/3部分将从原始的
    缓冲区创建一个子二进制文件,而不是分配一个新的二进制文件。我不知道这听起来很有用,获取所需的二进制文件仍然需要两个步骤,但可能非常快。你确定
    frame=
    将共享原始二进制文件吗?我刚刚创建了一个包含单个帧的1M字节缓冲区,并创建了一个100个
    的列表,我的内存使用量增加了100MB。另一方面,如果我创建一个包含100个
    frame=:binary.part(buffer,09999999)
    的列表,我的内存使用率保持不变。是的,但这是一个编译时优化。请参见页面上的匹配上下文。
    << frame = <<length::24, _::48, _::binary-size(length)>>, rest::binary>>
    
    def matcher(buffer)
      with <<length::24, b::48, c::binary-size(length), rest::binary>> <- buffer do 
        {:ok, <<length::24, b::48, c::binary-size(length)>>, rest}
      else
        other -> {:error, other}
      end
    end
    
    {:ok, frame, rest} = matcher(buffer)