zf

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

tsvector.ex (2075B)


      1 defmodule Postgrex.Extensions.TSVector do
      2   @moduledoc false
      3 
      4   import Postgrex.BinaryUtils, warn: false
      5   use Postgrex.BinaryExtension, send: "tsvectorsend"
      6 
      7   def encode(_) do
      8     quote location: :keep do
      9       values when is_list(values) ->
     10         encoded_tsvectors = unquote(__MODULE__).encode_tsvector(values)
     11         <<byte_size(encoded_tsvectors)::int32(), encoded_tsvectors::binary>>
     12 
     13       other ->
     14         raise DBConnection.EncodeError, Postgrex.Utils.encode_msg(other, "a list of tsvectors")
     15     end
     16   end
     17 
     18   def decode(_) do
     19     quote do
     20       <<len::int32(), value::binary-size(len)>> ->
     21         <<nb_lexemes::int32(), words::binary>> = value
     22         unquote(__MODULE__).decode_tsvector_values(words)
     23     end
     24   end
     25 
     26   ## Helpers
     27 
     28   def encode_tsvector(values) do
     29     <<length(values)::int32(), encode_lexemes(values)::binary>>
     30   end
     31 
     32   defp encode_lexemes(values) do
     33     values |> Enum.map(fn x -> encode_positions(x) end) |> IO.iodata_to_binary()
     34   end
     35 
     36   defp encode_positions(%Postgrex.Lexeme{word: word, positions: positions}) do
     37     positions =
     38       Enum.map(positions, fn {position, weight} ->
     39         <<encode_weight_binary(weight)::2, position::14>>
     40       end)
     41 
     42     [word, 0, <<length(positions)::16>> | positions]
     43   end
     44 
     45   def decode_tsvector_values("") do
     46     []
     47   end
     48 
     49   def decode_tsvector_values(words) do
     50     [word, <<positions_count::16, rest::binary>>] = :binary.split(words, <<0>>)
     51     positions_bytes = positions_count * 2
     52     <<positions::binary-size(positions_bytes), remaining_data::binary>> = rest
     53 
     54     positions =
     55       for <<weight::2, position::14 <- positions>>, do: {position, decode_weight(weight)}
     56 
     57     [%Postgrex.Lexeme{word: word, positions: positions} | decode_tsvector_values(remaining_data)]
     58   end
     59 
     60   defp encode_weight_binary(:A) do
     61     3
     62   end
     63 
     64   defp encode_weight_binary(:B) do
     65     2
     66   end
     67 
     68   defp encode_weight_binary(:C) do
     69     1
     70   end
     71 
     72   defp encode_weight_binary(nil) do
     73     0
     74   end
     75 
     76   defp decode_weight(0), do: nil
     77   defp decode_weight(1), do: :C
     78   defp decode_weight(2), do: :B
     79   defp decode_weight(3), do: :A
     80 end