Elixir 位串包含 sub-bitstring

Elixir bitstring contains sub-bitstring

我想检查一个长位串中是否包含另一个位串。类似于:

if MyBitstringModule.contains(<<1, 2, 3, 4, 5>>, <<2, 3, 4>>) do
  # do stuff
end

如果我有 二进制文件,这将非常简单:我可以使用 the =~ operator or String.contains?/2。但是,这两个都只对二进制文件进行操作,因此在大小不能被 8 整除的位串上会失败。

到目前为止,我想出的最好的方法是像这样的递归模式匹配(实际上没有用!),这看起来像是一个拼凑:

def contains(haystack, needle) when is_bitstring(haystack) and is_bitstring(needle) do
  needle_size = bit_size(needle)
  case haystack do
    <<>> -> false
    <<^needle::size(needle_size), _::bitstring>> -> true
    <<_::size(1), remainder::bitstring>> -> contains(remainder, needle)
  end
end

[请注意,尽管标题或多或少相同,但这实际上并不是 this question 的重复——链接的问题及其答案都涉及 二进制文件 仅。]

编辑:我上面的测试用例很糟糕,因为两个参数实际上都是二进制文件。更好的测试用例是:

iex> contains(<<1, 2, 3, 4, 5, 1::size(1)>>, <<2, 3, 4>>)
true
iex> contains(<<1, 2, 3, 4, 5, 1::size(1)>>, <<4, 5, 1::size(1)>>)
true

bitstring 类型添加到您的真实案例中对我有用

<<^needle::bitstring-size(needle_size), _::bitstring>> -> true

如果你直接在上面尝试匹配

iex> needle = <<3, 4, 5>>
<<3, 4, 5>>
iex> needle_size = bit_size(needle)
24
iex> <<^needle::size(needle_size), _::bitstring>> = <<3, 4, 5>>
** (MatchError) no match of right hand side value: <<3, 4, 5>>
iex> <<^needle::bitstring-size(needle_size), _::bitstring>> = <<3, 4, 5>>
<<3, 4, 5>>