defmodule Bolt.Sips.Internals.PackStream.EncoderV2 do @moduledoc false use Bolt.Sips.Internals.PackStream.Markers alias Bolt.Sips.Internals.PackStream.EncoderHelper alias Bolt.Sips.Types.{TimeWithTZOffset, DateTimeWithTZOffset, Duration, Point} @doc """ Encode a Time (represented by Time) into Bolt binary format. Encoded in a structure. Signature: `0x74` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nanoseconds_from_00:00:00` ## Example iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_local_time(~T[06:54:32.453], 2)) <<0xB1, 0x74, 0xCB, 0x0, 0x0, 0x16, 0x9F, 0x11, 0xB9, 0xCB, 0x40>> """ @spec encode_local_time(Time.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_local_time(local_time, bolt_version), do: EncoderHelper.call_encode(:local_time, local_time, bolt_version) @doc """ Encode a TIME WITH TIMEZONE OFFSET (represented by TimeWithTZOffset) into Bolt binary format. Encoded in a structure. Signature: `0x54` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nanoseconds_from_00:00:00` `Offset_in_seconds` ## Example iex> time_with_tz = Bolt.Sips.Types.TimeWithTZOffset.create(~T[06:54:32.453], 3600) iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_time_with_tz(time_with_tz, 2)) <<0xB2, 0x54, 0xCB, 0x0, 0x0, 0x16, 0x9F, 0x11, 0xB9, 0xCB, 0x40, 0xC9, 0xE, 0x10>> """ def encode_time_with_tz(%TimeWithTZOffset{time: time, timezone_offset: offset}, bolt_version), do: EncoderHelper.call_encode(:time_with_tz, %TimeWithTZOffset{time: time, timezone_offset: offset}, bolt_version ) @doc """ Encode a DATE (represented by Date) into Bolt binary format. Encoded in a structure. Signature: `0x44` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nb_days_since_epoch` ## Example iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_date(~D[2019-04-23], 2)) <<0xB1, 0x44, 0xC9, 0x46, 0x59>> """ @spec encode_date(Date.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_date(date, bolt_version), do: EncoderHelper.call_encode(:date, date, bolt_version) @doc """ Encode a LOCAL DATETIME (Represented by NaiveDateTime) into Bolt binary format. Encoded in a structure. WARNING: Nanoseconds are left off as NaiveDateTime doesn't handle them. A new Calendar should be implemented to manage them. Signature: `0x64` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nb_seconds_since_epoch` `Remainder_in_nanoseconds` ## Example iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_local_datetime(~N[2019-04-23 13:45:52.678], 2)) <<0xB2, 0x64, 0xCA, 0x5C, 0xBF, 0x17, 0x10, 0xCA, 0x28, 0x69, 0x75, 0x80>> """ @spec encode_local_datetime(Calendar.naive_datetime(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_local_datetime(local_datetime, bolt_version), do: EncoderHelper.call_encode(:local_datetime, local_datetime, bolt_version) @doc """ Encode DATETIME WITH TIMEZONE ID (represented by Calendar.DateTime) into Bolt binary format. Encoded in a structure. WARNING: Nanoseconds are left off as NaiveDateTime doesn't handle them. A new Calendar should be implemented to manage them. Signature: `0x66` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nb_seconds_since_epoch` `Remainder_in_nanoseconds` `Zone_id` ## Example iex> d = Bolt.Sips.TypesHelper.datetime_with_micro(~N[2013-11-12 07:32:02.003], ...> "Europe/Berlin") #DateTime<2013-11-12 07:32:02.003+01:00 CET Europe/Berlin> iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_datetime_with_tz_id(d, 2)) <<0xB3, 0x66, 0xCA, 0x52, 0x81, 0xD9, 0x72, 0xCA, 0x0, 0x2D, 0xC6, 0xC0, 0x8D, 0x45, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2F, 0x42, 0x65, 0x72, 0x6C, 0x69, 0x6E>> """ @spec encode_datetime_with_tz_id(Calendar.datetime(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_datetime_with_tz_id(datetime, bolt_version), do: EncoderHelper.call_encode(:datetime_with_tz_id, datetime, bolt_version) @doc """ Encode DATETIME WITH TIMEZONE OFFSET (represented by DateTimeWithTZOffset) into Bolt binary format. Encoded in a structure. WARNING: Nanoseconds are left off as NaiveDateTime doesn't handle them. A new Calendar should be implemented to manage them. Signature: `0x46` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Nb_seconds_since_epoch` `Remainder_in_nanoseconds` `Zone_offset` ## Example iex> d = Bolt.Sips.Types.DateTimeWithTZOffset.create(~N[2013-11-12 07:32:02.003], 7200) %Bolt.Sips.Types.DateTimeWithTZOffset{ naive_datetime: ~N[2013-11-12 07:32:02.003], timezone_offset: 7200 } iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_datetime_with_tz_offset(d, 2)) <<0xB3, 0x46, 0xCA, 0x52, 0x81, 0xD9, 0x72, 0xCA, 0x0, 0x2D, 0xC6, 0xC0, 0xC9, 0x1C, 0x20>> """ @spec encode_datetime_with_tz_offset(DateTimeWithTZOffset.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_datetime_with_tz_offset( %DateTimeWithTZOffset{naive_datetime: ndt, timezone_offset: tz_offset}, bolt_version ), do: EncoderHelper.call_encode(:datetime_with_tz_offset, %DateTimeWithTZOffset{naive_datetime: ndt, timezone_offset: tz_offset}, bolt_version ) @doc """ Encode DURATION (represented by Duration) into Bolt binary format. Encoded in a structure. Signature: `0x45` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `Months` `Days` `Seconds` `Nanoseconds` ## Example iex(60)> d = %Bolt.Sips.Types.Duration{ ...(60)> years: 3, ...(60)> months: 1, ...(60)> weeks: 7, ...(60)> days: 4, ...(60)> hours: 13, ...(60)> minutes: 2, ...(60)> seconds: 21, ...(60)> nanoseconds: 554 ...(60)> } %Bolt.Sips.Types.Duration{ days: 4, hours: 13, minutes: 2, months: 1, nanoseconds: 554, seconds: 21, weeks: 7, years: 3 } iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_duration(d, 2)) <<0xB4, 0x45, 0x25, 0x35, 0xCA, 0x0, 0x0, 0xB7, 0x5D, 0xC9, 0x2, 0x2A>> """ @spec encode_duration(Duration.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_duration(%Duration{} = duration, bolt_version), do: EncoderHelper.call_encode(:duration, duration, bolt_version) @doc """ Encode POINT 2D & 3D (represented by Point) into Bolt binary format. Encoded in a structure. ## Point 2D Signature: `0x58` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `SRID` `x_or_longitude` `y_or_latitude` ## Example iex> p = Bolt.Sips.Types.Point.create(:wgs_84, 65.43, 12.54) %Bolt.Sips.Types.Point{ crs: "wgs-84", height: nil, latitude: 12.54, longitude: 65.43, srid: 4326, x: 65.43, y: 12.54, z: nil } iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_point(p, 2)) <<0xB3, 0x58, 0xC9, 0x10, 0xE6, 0xC1, 0x40, 0x50, 0x5B, 0x85, 0x1E, 0xB8, 0x51, 0xEC, 0xC1, 0x40, 0x29, 0x14, 0x7A, 0xE1, 0x47, 0xAE, 0x14>> ## Point 3D Signature: `0x58` Encoding: `Marker` `Size` `Signature` ` Content` where `Content` is: `SRID` `x_or_longitude` `y_or_latitude` `z_or_height` ## Example iex> p = Bolt.Sips.Types.Point.create(:wgs_84, 45.0003, 40.3245, 23.1) %Bolt.Sips.Types.Point{ crs: "wgs-84-3d", height: 23.1, latitude: 40.3245, longitude: 45.0003, srid: 4979, x: 45.0003, y: 40.3245, z: 23.1 } iex> :erlang.iolist_to_binary(Bolt.Sips.Internals.PackStream.EncoderV2.encode_point(p, 2)) <<0xB4, 0x59, 0xC9, 0x13, 0x73, 0xC1, 0x40, 0x46, 0x80, 0x9, 0xD4, 0x95, 0x18, 0x2B, 0xC1, 0x40, 0x44, 0x29, 0x89, 0x37, 0x4B, 0xC6, 0xA8, 0xC1, 0x40, 0x37, 0x19, 0x99, 0x99, 0x99, 0x99, 0x9A>> """ @spec encode_point(Point.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_point(%Point{z: nil} = point, bolt_version), do: EncoderHelper.call_encode(:point, point, bolt_version) def encode_point(%Point{} = point, bolt_version), do: EncoderHelper.call_encode(:point, point, bolt_version) end