zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

hstore.ex (2723B)


      1 defmodule Postgrex.Extensions.HStore do
      2   @moduledoc false
      3   import Postgrex.BinaryUtils, warn: false
      4   use Postgrex.BinaryExtension, type: "hstore"
      5 
      6   def init(opts), do: Keyword.fetch!(opts, :decode_binary)
      7 
      8   def encode(_) do
      9     quote location: :keep do
     10       %{} = map ->
     11         data = unquote(__MODULE__).encode_hstore(map)
     12         [<<IO.iodata_length(data)::int32()>> | data]
     13 
     14       other ->
     15         raise DBConnection.EncodeError, Postgrex.Utils.encode_msg(other, "a map")
     16     end
     17   end
     18 
     19   def decode(mode) do
     20     quote do
     21       <<len::int32(), data::binary-size(len)>> ->
     22         unquote(__MODULE__).decode_hstore(data, unquote(mode))
     23     end
     24   end
     25 
     26   ## Helpers
     27 
     28   def encode_hstore(hstore_map) do
     29     keys_and_values =
     30       Enum.reduce(hstore_map, "", fn {key, value}, acc ->
     31         [acc, encode_hstore_key(key), encode_hstore_value(value)]
     32       end)
     33 
     34     [<<map_size(hstore_map)::int32()>> | keys_and_values]
     35   end
     36 
     37   defp encode_hstore_key(key) when is_binary(key) do
     38     encode_hstore_value(key)
     39   end
     40 
     41   defp encode_hstore_key(key) when is_nil(key) do
     42     raise ArgumentError, "hstore keys cannot be nil!"
     43   end
     44 
     45   defp encode_hstore_value(nil) do
     46     <<-1::int32()>>
     47   end
     48 
     49   defp encode_hstore_value(value) when is_binary(value) do
     50     value_byte_size = byte_size(value)
     51     <<value_byte_size::int32()>> <> value
     52   end
     53 
     54   def decode_hstore(<<_length::int32(), pairs::binary>>, :reference) do
     55     decode_hstore_ref(pairs, %{})
     56   end
     57 
     58   def decode_hstore(<<_length::int32(), pairs::binary>>, :copy) do
     59     decode_hstore_copy(pairs, %{})
     60   end
     61 
     62   defp decode_hstore_ref(<<>>, acc) do
     63     acc
     64   end
     65 
     66   # in the case of a NULL value, there won't be a length
     67   defp decode_hstore_ref(
     68          <<key_length::int32(), key::binary(key_length), -1::int32(), rest::binary>>,
     69          acc
     70        ) do
     71     decode_hstore_ref(rest, Map.put(acc, key, nil))
     72   end
     73 
     74   defp decode_hstore_ref(
     75          <<key_length::int32(), key::binary(key_length), value_length::int32(),
     76            value::binary(value_length), rest::binary>>,
     77          acc
     78        ) do
     79     decode_hstore_ref(rest, Map.put(acc, key, value))
     80   end
     81 
     82   defp decode_hstore_copy(<<>>, acc) do
     83     acc
     84   end
     85 
     86   # in the case of a NULL value, there won't be a length
     87   defp decode_hstore_copy(
     88          <<key_length::int32(), key::binary(key_length), -1::int32(), rest::binary>>,
     89          acc
     90        ) do
     91     decode_hstore_copy(rest, Map.put(acc, :binary.copy(key), nil))
     92   end
     93 
     94   defp decode_hstore_copy(
     95          <<key_length::int32(), key::binary(key_length), value_length::int32(),
     96            value::binary(value_length), rest::binary>>,
     97          acc
     98        ) do
     99     decode_hstore_copy(rest, Map.put(acc, :binary.copy(key), :binary.copy(value)))
    100   end
    101 end