Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and modernization of the library #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config/config.exs

This file was deleted.

66 changes: 42 additions & 24 deletions lib/zbar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand Down
9 changes: 5 additions & 4 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
19 changes: 11 additions & 8 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -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"},
}