File size: 2,560 Bytes
a8d7371
c7a94c4
 
 
 
 
a8d7371
 
 
 
 
491462f
 
 
 
a8d7371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b2415c
 
 
 
 
 
 
 
 
 
a8d7371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
defmodule Srh.Http.ResultEncoder do
  # Authentication errors don't get encoded, we need to skip over those
  def encode_response({:not_authorized, message}) do
    {:not_authorized, message}
  end

  # Errors don't get encoded, we need to skip over those
  def encode_response({:redis_error, error_result_map}) do
    {:redis_error, error_result_map}
  end

  def encode_response({:connection_error, error_result_map}) do
    {:connection_error, error_result_map}
  end

  # List-based responses, they will contain multiple entries
  # It's important to note that this is DIFFERENT from a list of values,
  # as it's a list of separate command responses. Each is a map that either
  # Contains a result or an error
  def encode_response({:ok, result_list}) when is_list(result_list) do
    # Each one of these entries needs to be encoded
    {:ok, encode_response_list(result_list, [])}
  end

  # Single item response
  def encode_response({:ok, %{result: result_value}}) do
    {:ok, %{result: encode_result_value(result_value)}}
  end

  ## RESULT LIST ENCODING ##

  defp encode_response_list([current | rest], encoded_responses) do
    encoded_current_entry =
      case current do
        %{result: value} ->
          # Encode the value
          %{result: encode_result_value(value)}

        %{error: error_message} ->
          # We don't encode errors
          %{error: error_message}
      end

    encode_response_list(rest, [encoded_current_entry | encoded_responses])
  end

  defp encode_response_list([], encoded_responses) do
    Enum.reverse(encoded_responses)
  end

  ## RESULT VALUE ENCODING ##

  # Numbers are ignored
  defp encode_result_value(value) when is_number(value), do: value

  # Null/nil is ignored
  defp encode_result_value(value) when is_nil(value), do: value

  # Strings / blobs (any binary data) is encoded to Base64
  defp encode_result_value(value) when is_binary(value), do: Base.encode64(value)

  defp encode_result_value(arr) when is_list(arr) do
    encode_result_value_list(arr, [])
  end

  ## RESULT VALUE LIST ENCODING ##

  # Arrays can have values that are encoded, or aren't, based on whats laid out above
  defp encode_result_value_list([current | rest], encoded_responses) do
    encoded_value = encode_result_value(current)
    encode_result_value_list(rest, [encoded_value | encoded_responses])
  end

  defp encode_result_value_list([], encoded_responses) do
    # There are no responses left, and since we add them backwards, we need to flip the list
    Enum.reverse(encoded_responses)
  end
end