 
   @doc """
   Returns the default port for a given SIP scheme.
-  If the scheme is unknown to the `URI` module, this function returns `nil`.
+  If the scheme is unknown to the `Sippet.URI` module, this function returns
+  `nil`.
   ## Examples
       iex> Sippet.URI.default_port("sip")
       5060

  """
  @spec decode_headers(binary) :: map
  def decode_headers(headers, map \\ %{}) do
    cond do
      headers == "" -> map
      String.starts_with?(headers, "?") ->
        decode_headers_into_map(
            String.slice(headers, 1, String.length(headers)-1), map)
      :otherwise ->
        raise ArgumentError,
            "decode_headers/1 string has to start with ';', "
            <> "got: #{inspect headers}"
    end
  end

  defp decode_headers_into_map(headers, map) do
    case decode_next_pair(headers, "&") do
      nil -> map
      {{key, value}, rest} ->
        decode_headers_into_map(rest, Map.put(map, key, value))
    end
  end

  @doc """

  """
  @spec encode_parameters(term) :: binary
  def encode_parameters(enumerable) do
    wrap("encode_parameters/1", ";", ";", enumerable, &encode_paramchar/1)
  end

  defp wrap(function_name, first_character, separator, enumerable, encode) do
    first_character <> Enum.map_join(enumerable, separator,
      &encode_pair(function_name, encode, &1))
  end

  defp encode_pair(function_name, _encode, {key, _}) when is_list(key) do
    raise ArgumentError, function_name <> " keys cannot be lists, "
                         <> "got: #{inspect key}"
  end

  defp encode_pair(function_name, _encode, {_, value}) when is_list(value) do
    raise ArgumentError, function_name <> " values cannot be lists, "
                         <> "got: #{inspect value}"
  end

  defp encode_pair(_function_name, encode, {key, nil}) do
    encode.(Kernel.to_string(key))
  end

  defp encode_pair(_function_name, encode, {key, value}) do
    encode.(Kernel.to_string(key)) <>
      "=" <> encode.(Kernel.to_string(value))
  end

  @doc """
