defmodule MishkaDeveloperTools.Helper.UUID do @moduledoc """ **To make the UUID, this module is completely copied from the ecto project under the Apache License 2.0.** **For more information and more functions, please refer to the following path:** - https://github.com/elixir-ecto/ecto/blob/v3.11.2/lib/ecto/uuid.ex#L1 - https://hexdocs.pm/ecto/Ecto.UUID.html > It should be noted that this file only supports uuid version 4. > To use other versions in hex, look for another library """ @type t :: <<_::288>> @type raw :: <<_::128>> defmodule HelperEcto.CastError do @moduledoc """ Raised when a changeset can't cast a value. """ defexception [:message, :type, :value] def exception(opts) do type = Keyword.fetch!(opts, :type) value = Keyword.fetch!(opts, :value) msg = opts[:message] || "cannot cast #{inspect(value)} to #{format(type)}" %__MODULE__{message: msg, type: type, value: value} end @doc """ Format type for error messaging and logs. """ def format({composite, type}) when composite in [:array, :map] do "{#{inspect(composite)}, #{format(type)}}" end def format({:parameterized, type, params}) do if function_exported?(type, :format, 1) do apply(type, :format, [params]) else "##{inspect(type)}<#{inspect(params)}>" end end def format(type), do: inspect(type) end @spec cast(t | raw | any) :: {:ok, t} | :error def cast(uuid) def cast( <> ) do <> catch :error -> :error else hex_uuid -> {:ok, hex_uuid} end def cast(<<_::128>> = raw_uuid), do: {:ok, encode(raw_uuid)} def cast(_), do: :error @spec cast!(t | raw | any) :: t def cast!(uuid) do case cast(uuid) do {:ok, hex_uuid} -> hex_uuid :error -> raise HelperEcto.CastError, type: __MODULE__, value: uuid end end @compile {:inline, c: 1} defp c(?0), do: ?0 defp c(?1), do: ?1 defp c(?2), do: ?2 defp c(?3), do: ?3 defp c(?4), do: ?4 defp c(?5), do: ?5 defp c(?6), do: ?6 defp c(?7), do: ?7 defp c(?8), do: ?8 defp c(?9), do: ?9 defp c(?A), do: ?a defp c(?B), do: ?b defp c(?C), do: ?c defp c(?D), do: ?d defp c(?E), do: ?e defp c(?F), do: ?f defp c(?a), do: ?a defp c(?b), do: ?b defp c(?c), do: ?c defp c(?d), do: ?d defp c(?e), do: ?e defp c(?f), do: ?f defp c(_), do: throw(:error) @spec generate() :: t def generate(), do: encode(bingenerate()) @spec bingenerate() :: raw def bingenerate() do <> = :crypto.strong_rand_bytes(16) <> end @doc false def autogenerate, do: generate() @spec encode(raw) :: t defp encode( <> ) do <> end @compile {:inline, e: 1} defp e(0), do: ?0 defp e(1), do: ?1 defp e(2), do: ?2 defp e(3), do: ?3 defp e(4), do: ?4 defp e(5), do: ?5 defp e(6), do: ?6 defp e(7), do: ?7 defp e(8), do: ?8 defp e(9), do: ?9 defp e(10), do: ?a defp e(11), do: ?b defp e(12), do: ?c defp e(13), do: ?d defp e(14), do: ?e defp e(15), do: ?f end