この記事は「Elixir Advent Calendar 2022その1」2日目の記事です.
はじめに
本記事は以下のElixir特集のパターンマッチの章でページ数の関係上削られたので、こちらで供養します
バイナリデータのパターンマッチについて紹介します。
基本的な使い方
バイナリデータは、ビットストリングを表す<<>>
記号の内側で、セグメントごとにパターンマッチを行うことができます。
iex> a = "abc"
"abc"
iex> <<b, c, d>> = a
"abc"
iex> {b, c, d}
{97, 98, 99}
bits
やbinary-size
修飾子を使用して、残りすべてのビットや指定したビット数にマッチさせることができます。
iex> a = "abc"
"abc"
iex> <<b, c::bits>> = a
"abc"
iex> b
97
iex> c
"bc"
iex> a = "abcde"
"abcde"
iex> <<b::binary-size(2), c::binary-size(3)>> = a
"abcde"
iex> b
"ab"
iex> c
"cde
範囲外をマッチさせようとするとマッチエラーになります。
iex> a = "abcde"
"abcde"
iex> <<b::binary-size(2), c::binary-size(4)>> = a
** (MatchError) no match of right hand side value: "abcde"
実践的な使い方
バイナリデータ画像のヘッダのバイナリから、画像形式を判別する関数を実装します。実行する前に、IExを実行するフォルダにPNG形式の画像をimage.png
として保存しておいてください。
iex> defmodule WebDB.Binary do
...> def mime(<<0x89, "PNG", _::bits>>), do: "png"
...> def mime(<<"GIF", 0x38, _::bits>>), do: "gif"
...> def mime(<<0xFF, 0xD8, _::bits>>), do: "jpg"
...> def mime(_), do: "unsupported file"
...> end
{:module, WebDB.Binary, <<(省略)>>, {:mime, 1}}
iex> {:ok, file} = File.read("image.png")
iex> WebDB.Binary.mime(file)
"png"
iex> WebDB.Binary.mime(1)
"unsupported file"
最後に
バイナリデータのパターンマッチマッチについていくつか例を紹介してきました
このパターンマッチはセンサーデータでも有用なのでいろいろ試してみてください
バイナリデータ以外のパターンマッチはWebDBPressの方で記事になっていますので是非買って読んでみてください
本記事は以上になりますありがとうございました