diff --git a/config/config.exs b/config/config.exs deleted file mode 100644 index d2d855e..0000000 --- a/config/config.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/lib/zbar.ex b/lib/zbar.ex index 1f8296e..cae249d 100644 --- a/lib/zbar.ex +++ b/lib/zbar.ex @@ -20,9 +20,9 @@ defmodule Zbar do * `{:error, binary()}` if there was an error in the scanning process """ @spec scan(binary(), pos_integer()) :: - {:ok, list(Zbar.Symbol.t())} - | {:error, :timeout} - | {:error, binary()} + {:ok, list(Zbar.Symbol.t())} + | {:error, :timeout} + | {:error, binary()} def scan(jpeg_data, timeout \\ 5000) do # We run this in a `Task` so that `collect_output` can use `receive` # without interfering with the caller's mailbox. @@ -31,15 +31,16 @@ defmodule Zbar do end @spec do_scan(binary(), pos_integer()) :: - {:ok, [Zbar.Symbol.t()]} - | {:error, :timeout} - | {:error, binary()} + {:ok, [Zbar.Symbol.t()]} + | {:error, :timeout} + | {:error, binary()} defp do_scan(jpeg_data, timeout) do - File.open!(temp_file(), [:write, :binary], & IO.binwrite(&1, jpeg_data)) + temp_file = temp_file() + File.open!(temp_file, [:write, :binary], &IO.binwrite(&1, jpeg_data)) {:spawn_executable, to_charlist(zbar_binary())} |> Port.open([ - {:args, [temp_file()]}, + {:args, [temp_file]}, :binary, :stream, :exit_status, @@ -54,35 +55,44 @@ defmodule Zbar do |> String.split("\n", trim: true) |> Enum.map(&parse_symbol/1) + File.rm(temp_file) {:ok, symbols} {:error, reason} -> + File.rm(temp_file) {:error, reason} end end @spec temp_file() :: binary() - defp temp_file, do: Path.join(System.tmp_dir!(), "zbar_image.jpg") + defp temp_file do + file = Nanoid.generate() <> ".jpg" + Path.join(System.tmp_dir!(), file) + end @spec zbar_binary() :: binary() defp zbar_binary, do: Path.join(:code.priv_dir(:zbar), "zbar_scanner") @spec collect_output(port(), pos_integer(), binary()) :: - {:ok, binary()} - | {:error, :timeout} - | {:error, binary()} + {:ok, binary()} + | {:error, :timeout} + | {:error, binary()} defp collect_output(port, timeout, buffer \\ "") do receive do {^port, {:data, "Premature end of JPEG file\n"}} -> # Handles an error condition described in https://github.com/elixir-vision/zbar-elixir/issues/1 collect_output(port, timeout, buffer) + {^port, {:data, data}} -> collect_output(port, timeout, buffer <> to_string(data)) + {^port, {:exit_status, 0}} -> {:ok, buffer} + {^port, {:exit_status, _}} -> {:error, buffer} - after timeout -> + after + timeout -> Port.close(port) {:error, :timeout} end @@ -103,19 +113,27 @@ defmodule Zbar do string |> String.split(" ") |> Enum.reduce(%Symbol{}, fn item, acc -> - [key, value] = String.split(item, ":", parts: 2) - case key do - "type" -> - %Symbol{acc | type: parse_type(value)} + case String.split(item, ":", parts: 2) do + [key, value] -> + case key do + "type" -> + %Symbol{acc | type: parse_type(value)} + + "quality" -> + %Symbol{acc | quality: String.to_integer(value)} + + "points" -> + %Symbol{acc | points: parse_points(value)} - "quality" -> - %Symbol{acc | quality: String.to_integer(value)} + "data" -> + %Symbol{acc | data: Base.decode64!(value)} - "points" -> - %Symbol{acc | points: parse_points(value)} + _ -> + acc + end - "data" -> - %Symbol{acc | data: Base.decode64!(value)} + _ -> + acc end end) end @@ -138,7 +156,7 @@ defmodule Zbar do defp parse_points(string) do string |> String.split(";") - |> Enum.map(& parse_point/1) + |> Enum.map(&parse_point/1) end @spec parse_point(binary()) :: Zbar.Symbol.point() diff --git a/mix.exs b/mix.exs index d5fc08b..b487a39 100644 --- a/mix.exs +++ b/mix.exs @@ -11,11 +11,11 @@ defmodule Zbar.Mixfile do make_clean: ["clean"], compilers: [:elixir_make | Mix.compilers()], build_embedded: true, - start_permanent: Mix.env == :prod, - compilers: [:elixir_make] ++ Mix.compilers, + start_permanent: Mix.env() == :prod, + compilers: [:elixir_make] ++ Mix.compilers(), package: package(), deps: deps(), - dialyzer: [plt_add_apps: [:mix]], + dialyzer: [plt_add_apps: [:mix, :nanoid]], docs: docs() ] end @@ -27,8 +27,9 @@ defmodule Zbar.Mixfile do defp deps do [ {:elixir_make, "~> 0.6", runtime: false}, - {:dialyxir, "~> 1.0.0-rc.6", only: :dev, runtime: false}, + {:dialyxir, "~> 1.3", only: :dev, runtime: false}, {:ex_doc, "~> 0.21", only: :dev, runtime: false}, + {:nanoid, "~> 2.0", runtime: false} ] end diff --git a/mix.lock b/mix.lock index 66ad172..e94da14 100644 --- a/mix.lock +++ b/mix.lock @@ -1,10 +1,13 @@ %{ - "dialyxir": {:hex, :dialyxir, "1.0.0-rc.6", "78e97d9c0ff1b5521dd68041193891aebebce52fc3b93463c0a6806874557d7d", [:mix], [{:erlex, "~> 0.2.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}, - "earmark": {:hex, :earmark, "1.3.5", "0db71c8290b5bc81cb0101a2a507a76dca659513984d683119ee722828b424f6", [:mix], [], "hexpm"}, - "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"}, - "erlex": {:hex, :erlex, "0.2.4", "23791959df45fe8f01f388c6f7eb733cc361668cbeedd801bf491c55a029917b", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.21.1", "5ac36660846967cd869255f4426467a11672fec3d8db602c429425ce5b613b90", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, + "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, + "earmark": {:hex, :earmark, "1.3.5", "0db71c8290b5bc81cb0101a2a507a76dca659513984d683119ee722828b424f6", [:mix], [], "hexpm", "762b999fd414fb41e297944228aa1de2cd4a3876a07f968c8b11d1e9a2190d07"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, + "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "ex_doc": {:hex, :ex_doc, "0.30.5", "aa6da96a5c23389d7dc7c381eba862710e108cee9cfdc629b7ec021313900e9e", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "88a1e115dcb91cefeef7e22df4a6ebbe4634fbf98b38adcbc25c9607d6d9d8e6"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, + "nanoid": {:hex, :nanoid, "2.1.0", "d192a5bf1d774258bc49762b480fca0e3128178fa6d35a464af2a738526607fd", [:mix], [], "hexpm", "ebc7a342d02d213534a7f93a091d569b9fea7f26fcd3a638dc655060fc1f76ac"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, }