Packages
ex_aws
2.5.8
2.7.0
2.6.1
2.6.0
2.5.11
2.5.10
2.5.9
2.5.8
2.5.7
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.9
2.1.8
2.1.7
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.2
2.0.1
2.0.0
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.1
1.0.0-beta3
1.0.0-beta2
1.0.0-beta1
1.0.0-beta0
0.5.0
0.4.19
0.4.18
0.4.17
0.4.15
0.4.14
0.4.13
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.1
0.3.0
0.2.0
0.1.2
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
AWS client for Elixir. Currently supports Dynamo, DynamoStreams, EC2, Firehose, Kinesis, KMS, Lambda, RRDS, Route53, S3, SES, SNS, SQS, STS and others.
Current section
Files
Jump to
Current section
Files
lib/ex_aws/utils.ex
defmodule ExAws.Utils do
@moduledoc false
def identity(x, _), do: x
# This isn't tail recursive. However, given that the structures
# being worked upon are relatively shallow, this is ok.
def camelize_keys(opts, kwargs \\ []) do
deep = kwargs[:deep] || false
spec = kwargs[:spec] || %{}
do_cmlz_keys(opts, deep: deep, spec: spec)
end
defp do_cmlz_keys([%{} | _] = opts, deep: deep, spec: spec) do
Enum.map(opts, &do_cmlz_keys(&1, deep: deep, spec: spec))
end
defp do_cmlz_keys(opts = %{}, deep: deep, spec: spec) do
opts
|> Enum.reduce(%{}, fn {k, v}, map ->
if deep do
Map.put(map, camelize_key(k, spec: spec), do_cmlz_keys(v, deep: true, spec: spec))
else
Map.put(map, camelize_key(k, spec: spec), v)
end
end)
end
defp do_cmlz_keys(opts, kwargs) do
try do
opts |> Map.new() |> do_cmlz_keys(kwargs)
rescue
[Protocol.UndefinedError, ArgumentError, FunctionClauseError] -> opts
end
end
def camelize_key(key, [spec: spec] \\ [spec: %{}]) do
spec[key] || key |> maybe_stringify |> camelize
end
def camelize(string) do
string
|> to_charlist
|> Enum.reduce({true, ~c""}, fn
?_, {_, acc} -> {true, acc}
?/, {_, acc} -> {false, [?. | acc]}
char, {false, acc} -> {false, [char | acc]}
char, {true, acc} -> {false, [upcase(char) | acc]}
end)
# charlist
|> elem(1)
# unreverses charlist after reducing
|> Enum.reverse()
|> to_string
end
def upcase(value) when is_atom(value), do: value |> Atom.to_string() |> String.upcase()
def upcase(value) when is_binary(value), do: String.upcase(value)
def upcase(char), do: :string.to_upper(char)
def uuid, do: DateTime.utc_now() |> :erlang.phash2()
def rename_keys(params, mapping) do
mapping = Map.new(mapping)
Enum.map(params, fn {k, v} ->
{Map.get(mapping, k, k), v}
end)
end
def format(params, kwargs \\ []) do
prefix = kwargs[:prefix] || ""
spec = kwargs[:spec] || %{}
case kwargs[:type] || :xml do
:xml ->
xml_format(params, prefix: prefix, spec: spec)
# :json -> json_format(params, prefix: prefix, spec: spec)
end
end
# NOTE: xml_format is not tail call optimized
# but it is unlikely that any AWS params will ever
# be nested enough for this to cause a stack overflow
# Indexed formats
defp xml_format([nested | _] = params, kwargs) when is_map(nested) do
params |> Enum.map(&Map.to_list/1) |> xml_format(kwargs)
end
defp xml_format([nested | _] = params, prefix: pre, spec: spec) when is_list(nested) do
params
|> Stream.with_index(1)
|> Stream.map(fn {params, i} -> {params, Integer.to_string(i)} end)
|> Stream.flat_map(fn {params, i} ->
xml_format(params, prefix: pre <> dot?(pre) <> i, spec: spec)
end)
|> Enum.to_list()
end
defp xml_format([param | _] = params, prefix: pre, spec: spec) when is_tuple(param) do
params
|> Stream.map(fn {key, values} -> {maybe_camelize(key, spec: spec), values} end)
|> Stream.flat_map(fn {key, values} ->
xml_format(values, prefix: pre <> dot?(pre) <> key, spec: spec)
end)
|> Enum.to_list()
end
# Non-indexed formats
defp xml_format(params, kwargs) when is_list(params) do
pre = kwargs[:prefix]
params
|> Stream.with_index(1)
|> Stream.map(fn {value, i} -> {value, Integer.to_string(i)} end)
|> Stream.map(fn {value, i} -> {pre <> dot?(pre) <> i, value} end)
|> Enum.to_list()
end
defp xml_format(params, kwargs) when is_map(params) do
xml_format(Map.to_list(params), kwargs)
end
defp xml_format(value, kwargs), do: [{kwargs[:prefix], value}]
defp dot?(""), do: ""
defp dot?(_), do: "."
def filter_nil_params(opts) do
opts
|> Enum.reject(fn {_key, value} -> value == nil end)
|> Enum.into(%{})
end
def maybe_camelize(elem, kwargs \\ [spec: %{}])
def maybe_camelize(elem, kwargs) when is_atom(elem), do: camelize_key(elem, kwargs)
def maybe_camelize(elem, _) when is_bitstring(elem), do: elem
def maybe_stringify(elem) when is_atom(elem), do: Atom.to_string(elem)
def maybe_stringify(elem) when is_bitstring(elem), do: elem
defmacro __using__(kwargs) do
camelize_inject =
quote do
[spec: unquote(kwargs[:non_standard_keys] || %{})] ++ kwargs
end
format_inject =
quote do
[type: unquote(kwargs[:format_type] || :xml)] ++ unquote(camelize_inject)
end
quote do
import ExAws.Utils,
except: [
format: 2,
format: 1,
camelize_keys: 2,
camelize_keys: 1,
camelize_key: 2,
camelize_key: 1,
maybe_camelize: 2,
maybe_camelize: 1
]
defp format(params, kwargs \\ []), do: ExAws.Utils.format(params, unquote(format_inject))
defp camelize_keys(opts, kwargs \\ []),
do: ExAws.Utils.camelize_keys(opts, unquote(camelize_inject))
defp camelize_key(opts, kwargs \\ []),
do: ExAws.Utils.camelize_key(opts, unquote(camelize_inject))
defp maybe_camelize(opts, kwargs \\ []),
do: ExAws.Utils.maybe_camelize(opts, unquote(camelize_inject))
end
end
end