Current section
Files
Jump to
Current section
Files
lib/data_url.ex
defmodule DataUrl do
@moduledoc """
Struct and functions for representing and parsing data: URLs
"""
@default_mime_type "text/plain;charset=US-ASCII"
defstruct mime_type: @default_mime_type, data: ""
@type t() :: %DataUrl{
mime_type: String.t(),
data: binary()
}
@doc """
Parse a data: URL into a %DataUrl{} struct
"""
@spec parse(String.t()) :: {:ok, DataUrl.t()} | {:error, any()}
def parse("data:" <> rest) do
String.split(rest, ",", parts: 2)
|> parse_parts
end
def parse(_), do: {:error, "missing \"data:\" scheme"}
defp parse_parts([_]), do: {:error, "missing comma"}
defp parse_parts([prefix, data]) do
with {:ok, data} <- parse_data(String.ends_with?(prefix, ";base64"), data),
prefix <- String.replace_suffix(prefix, ";base64", "") do
{:ok, %DataUrl{mime_type: get_mime_type(prefix), data: data}}
else
:error -> {:error, "invalid base64"}
x -> {:error, {"unknown error", x}}
end
end
defp get_mime_type(""), do: @default_mime_type
defp get_mime_type(mime_type) when is_binary(mime_type), do: mime_type
defp parse_data(true, data), do: Base.decode64(data)
defp parse_data(false, data), do: {:ok, URI.decode(data)}
end