Skip to content

Commit

Permalink
Refactorings + safe/unsafe parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Georgy Sychev committed Oct 29, 2019
1 parent bd84115 commit 74ee4d7
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 55 deletions.
59 changes: 8 additions & 51 deletions lib/wootheex.ex
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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
89 changes: 89 additions & 0 deletions lib/wootheex/user_agent.ex
Original file line number Diff line number Diff line change
@@ -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
11 changes: 7 additions & 4 deletions test/wootheex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 74ee4d7

Please sign in to comment.