defmodule Manganese.CoreKit do def is_uppercase_character(character) do character =~ ~r/^\p{Lu}$/u end def is_lowercase_character(character) do character =~ ~r/^\p{Ll}$/u end @doc """ Similar to `Macro.underscore` but with different handling of numbers in strings. For example, take the string `"asset3d"`. `Macro.underscore` returns simply `"asset3d". `underscore_key/1` returns `"asset_3d"` for consistency with the Foreverdaunt codebase when de/serializing JSON. """ @spec underscore_key(binary | atom | integer) :: binary def underscore_key(integer) when is_integer(integer), do: underscore_key Integer.to_string integer def underscore_key(atom) when is_atom(atom), do: underscore_key Atom.to_string atom def underscore_key(string) when is_binary(string) do string = Macro.underscore(string) string = Regex.replace(~r/([a-z]\d)/, string, fn _, pair -> "#{String.at(pair, 0)}_#{String.at(pair, 1)}" end) string end @doc """ Similar to `Macro.camelize` but with different handling of numbers in strings. """ @spec camelize_key(binary | atom | integer) :: binary def camelize_key(integer) when is_integer(integer), do: camelize_key Integer.to_string integer def camelize_key(atom) when is_atom(atom), do: camelize_key Atom.to_string atom def camelize_key(value) when is_binary(value) do first_character = value |> String.slice(0, 1) native_camelized = Macro.camelize value # The first character will be capitalized here if !is_uppercase_character first_character do String.downcase(first_character) <> String.slice(native_camelized, 1, String.length(native_camelized) - 1) else native_camelized end end @doc """ Generate a base64-encoded, cryptographically strong random string. """ def random_string(length) do :crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length) end end