Packages

An URI parser trying to be strictly compatible with RFC3986. Uses official ABNF grammar and ex_abnf as interpreter.

Current section

Files

Jump to
ex_rfc3986 lib normalize.ex
Raw

lib/normalize.ex

################################################################################
# Copyright 2015 Marcelo Gornstein <marcelog@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################
defmodule RFC3986.Normalize do
# fragment = *( pchar / "/" / "?" )
def parse(state = %{error: error}) when error != nil do
state
end
def parse(state) do
state |> port |> userinfo |> query_string
end
defp port(state = %{port: nil}) do
state
end
defp port(state) do
{p, _} = Integer.parse to_string(state.port)
%{state | port: p}
end
defp userinfo(state = %{userinfo: nil}) do
state
end
defp userinfo(state) do
userinfo state, state.userinfo, []
end
defp userinfo(state, [?:|rest], acc) do
%{state | username: Enum.reverse(acc), password: rest}
end
defp userinfo(state, [char|rest], acc) do
userinfo state, rest, [char|acc]
end
defp query_string(state = %{query: nil}) do
state
end
defp query_string(state) do
query_string state, state.query, []
end
defp query_string(state, [], []) do
state
end
defp query_string(state = %{query_string: map}, [], acc) do
k = Enum.reverse acc
%{state | query_string: Map.put(map, k, nil)}
end
defp query_string(state = %{query_string: map}, [?&|rest], acc) do
k = Enum.reverse acc
query_string %{state | query_string: Map.put(map, k, nil)}, rest, []
end
defp query_string(state = %{query_string: map}, [?=|rest], acc) do
k = Enum.reverse acc
{v, rest} = query_string_value rest
query_string %{state | query_string: Map.put(map, k, v)}, rest, []
end
defp query_string(state, [char|rest], acc) do
query_string state, rest, [char|acc]
end
defp query_string_value([]) do
{nil, []}
end
defp query_string_value(text) do
query_string_value text, []
end
defp query_string_value([], []) do
{nil, []}
end
defp query_string_value([], acc) do
{Enum.reverse(acc), []}
end
defp query_string_value([?&|rest], acc) do
{Enum.reverse(acc), rest}
end
defp query_string_value([char|rest], acc) do
query_string_value rest, [char|acc]
end
end