path.ex (1484B)
1 defmodule Postgrex.Extensions.Path do 2 @moduledoc false 3 import Postgrex.BinaryUtils, warn: false 4 use Postgrex.BinaryExtension, send: "path_send" 5 alias Postgrex.Extensions.Path 6 alias Postgrex.Extensions.Point 7 8 def encode(_) do 9 quote location: :keep, generated: true do 10 %Postgrex.Path{open: o, points: ps} when is_list(ps) and is_boolean(o) -> 11 open_byte = Path.open_to_byte(o) 12 len = length(ps) 13 14 encoded_points = 15 Enum.reduce(ps, [], fn p, acc -> [acc | Point.encode_point(p, Postgrex.Path)] end) 16 17 # 1 byte for open/closed flag, 4 for length, 16 for each point 18 nbytes = 5 + 16 * len 19 [<<nbytes::int32()>>, open_byte, <<len::int32()>> | encoded_points] 20 21 other -> 22 raise DBConnection.EncodeError, Postgrex.Utils.encode_msg(other, Postgrex.Path) 23 end 24 end 25 26 def decode(_) do 27 quote location: :keep do 28 <<nbytes::int32(), path_data::binary-size(nbytes)>> -> 29 Path.decode_path(path_data) 30 end 31 end 32 33 def decode_path(<<o::int8(), n::int32(), point_data::binary-size(n)-unit(128)>>) do 34 open = o == 0 35 points = decode_points(point_data, []) 36 %Postgrex.Path{open: open, points: points} 37 end 38 39 def open_to_byte(true), do: 0 40 def open_to_byte(false), do: 1 41 42 defp decode_points(<<>>, points), do: Enum.reverse(points) 43 44 defp decode_points(<<x::float64(), y::float64(), rest::bits>>, points) do 45 decode_points(rest, [%Postgrex.Point{x: x, y: y} | points]) 46 end 47 end