diff --git a/lib/wootheex.ex b/lib/wootheex.ex index a79a3ea..1b9b18e 100644 --- a/lib/wootheex.ex +++ b/lib/wootheex.ex @@ -1,52 +1,3 @@ -defmodule Wootheex.UserAgent do - alias Wootheex, as: W - @type parse_result_explicit :: %__MODULE__{ - category: W.category, - browser_name: W.browser_name, - browser_type: W.browser_type, - browser_version: W.browser_version, - os: W.os, - os_version: W.os_version, - vendor: W.vendor - } - @enforce_keys [:category, :browser_name, :browser_type, :browser_version, :os, :os_version, :vendor] - defstruct @enforce_keys - - @doc """ - Parse user agent to a struct - - iex> Wootheex.UserAgent.parse "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36" - %Wootheex.UserAgent{ - browser_name: "Chrome", - browser_type: :browser, - browser_version: "44.0.2403.155", - category: :pc, - os: "Mac OSX", - os_version: "10.10.4", - vendor: "Google" - } - - """ - @spec parse(W.user_agent) :: parse_result_explicit - def parse(ua) do - info = W.parse(ua) - {cat, bname, btype, bver, os, osver, vendor} = - case info do - :other -> {:other, :other, :other, :other, :other, :other, :other} - t when is_tuple(t) -> t - end - %__MODULE__{ - category: cat, - browser_name: bname, - browser_type: btype, - browser_version: bver, - os: os, - os_version: osver, - vendor: vendor - } - end -end - defmodule Wootheex do @type user_agent :: binary @@ -79,7 +30,13 @@ defmodule Wootheex do app = Mix.Project.config[:app] def load_dynlib() do - path = :filename.join([:code.priv_dir(unquote(app)), 'native', 'libwootheex_nif']) - :ok = :erlang.load_nif(path, 0) + :ok = + [:code.priv_dir(unquote(app)), 'native', 'libwootheex_nif'] + |> :filename.join() + |> :erlang.load_nif(0) end end + +defmodule WootheexError do + defexception [:message] +end diff --git a/lib/wootheex/user_agent.ex b/lib/wootheex/user_agent.ex new file mode 100644 index 0000000..d5d1679 --- /dev/null +++ b/lib/wootheex/user_agent.ex @@ -0,0 +1,89 @@ +defmodule Wootheex.UserAgent do + + @type t :: %__MODULE__{ + category: Wootheex.category(), + browser_name: Wootheex.browser_name(), + browser_type: Wootheex.browser_type(), + browser_version: Wootheex.browser_version(), + os: Wootheex.os(), + os_version: Wootheex.os_version(), + vendor: Wootheex.vendor() + } + @enforce_keys [ + :category, + :browser_name, + :browser_type, + :browser_version, + :os, + :os_version, + :vendor + ] + defstruct @enforce_keys + + @doc """ + Parse user agent to a struct or raises an error + + iex> Wootheex.UserAgent.parse! "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36" + %Wootheex.UserAgent{ + browser_name: "Chrome", + browser_type: :browser, + browser_version: "44.0.2403.155", + category: :pc, + os: "Mac OSX", + os_version: "10.10.4", + vendor: "Google" + } + + """ + @spec parse!(Wootheex.user_agent) :: t() + def parse!(ua) do + case Wootheex.parse(ua) do + :other -> raise WootheexError, "unknown user agent" + {cat, bname, btype, bver, os, osver, vendor} -> + %__MODULE__{ + category: cat, + browser_name: bname, + browser_type: btype, + browser_version: bver, + os: os, + os_version: osver, + vendor: vendor + } + end + end + + @doc """ + Safely parses user agent to a struct + + iex> Wootheex.UserAgent.parse "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36" + {:ok, + %Wootheex.UserAgent{ + browser_name: "Chrome", + browser_type: :browser, + browser_version: "44.0.2403.155", + category: :pc, + os: "Mac OSX", + os_version: "10.10.4", + vendor: "Google" + } + } + """ + @spec parse(Wootheex.user_agent) :: {:ok, t()} | {:error, any()} + def parse(ua) do + case Wootheex.parse(ua) do + :other -> {:error, "unknown user agent"} + {cat, bname, btype, bver, os, osver, vendor} -> + {:ok, + %__MODULE__{ + category: cat, + browser_name: bname, + browser_type: btype, + browser_version: bver, + os: os, + os_version: osver, + vendor: vendor + } + } + end + end +end diff --git a/test/wootheex_test.exs b/test/wootheex_test.exs index 3abcbcd..5924f84 100644 --- a/test/wootheex_test.exs +++ b/test/wootheex_test.exs @@ -3,15 +3,18 @@ defmodule WootheexTest do doctest Wootheex doctest Wootheex.UserAgent - alias Wootheex, as: W - test "Invalid argument (integer)" do number = 42 - assert_raise ArgumentError, fn -> assert W.parse(number) end + assert_raise ArgumentError, fn -> assert Wootheex.parse(number) end end test "Invalid UTF-8" do invalid_string = <<255, 1>> - assert_raise ArgumentError, fn -> assert W.parse(invalid_string) end + assert_raise ArgumentError, fn -> assert Wootheex.parse(invalid_string) end + end + + test "Invalid UserAgent" do + ua = "blahblahblahblahblahblahblahblahblah" + assert_raise WootheexError, fn -> assert Wootheex.UserAgent.parse!(ua) end end end