defmodule Bolt.Sips.Internals.PackStream.EncoderV1 do @moduledoc false alias Bolt.Sips.Internals.PackStream.EncoderHelper use Bolt.Sips.Internals.PackStream.Markers @doc """ Encode an atom into Bolt binary format. Encoding: `Marker` with | Value | Marker | | ------- | -------- | | nil | `0xC0` | | false | `0xC2` | | true | `0xC3` | Other atoms are converted to string before encoding. ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_atom(nil, 1)) <<0xC0>> iex> :erlang.iolist_to_binary(EncoderV1.encode_atom(true, 1)) <<0xC3>> iex> :erlang.iolist_to_binary(EncoderV1.encode_atom(:guten_tag, 1)) <<0x89, 0x67, 0x75, 0x74, 0x65, 0x6E, 0x5F, 0x74, 0x61, 0x67>> """ @spec encode_atom(atom(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_atom(atom , bolt_version), do: EncoderHelper.call_encode(:atom, atom, bolt_version) @doc """ Encode a string into Bolt binary format. Encoding: `Marker` `Size` `Content` with | Marker | Size | Max data size | |--------|------|---------------| | `0x80`..`0x8F` | None (contained in marker) | 15 bytes | | `0xD0` | 8-bit integer | 255 bytes | | `0xD1` | 16-bit integer | 65_535 bytes | | `0xD2` | 32-bit integer | 4_294_967_295 bytes | ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_string("guten tag", 1)) <<0x89, 0x67, 0x75, 0x74, 0x65, 0x6E, 0x20, 0x74, 0x61, 0x67>> """ @spec encode_string(String.t(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_string(string, bolt_version), do: EncoderHelper.call_encode(:string, string, bolt_version) @doc """ Encode an integer into Bolt binary format. Encoding: `Marker` `Value` with | | Marker | |---|--------| | tiny int | `0x2A` | | int8 | `0xC8` | | int16 | `0xC9` | | int32 | `0xCA` | | int64 | `0xCB` | ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_integer(74, 1)) <<0x4A>> iex> :erlang.iolist_to_binary(EncoderV1.encode_integer(-74_789, 1)) <<0xCA, 0xFF, 0xFE, 0xDB, 0xDB>> """ @spec encode_integer(integer(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_integer(integer, bolt_version), do: EncoderHelper.call_encode(:integer, integer, bolt_version) @doc """ Encode a float into Bolt binary format. Encoding: `Marker` `8 byte Content`. Marker: `0xC1` Formated according to the IEEE 754 floating-point "double format" bit layout. ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_float(42.42, 1)) <<0xC1, 0x40, 0x45, 0x35, 0xC2, 0x8F, 0x5C, 0x28, 0xF6>> """ @spec encode_float(float(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_float(number, bolt_version), do: EncoderHelper.call_encode(:float, number, bolt_version) @doc """ Encode a list into Bolt binary format. Encoding: `Marker` `Size` `Content` with | Marker | Size | Max list size | |--------|------|---------------| | `0x90`..`0x9F` | None (contained in marker) | 15 bytes | | `0xD4` | 8-bit integer | 255 items | | `0xD5` | 16-bit integer | 65_535 items | | `0xD6` | 32-bit integer | 4_294_967_295 items | ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_list(["hello", "world"], 1)) <<0x92, 0x85, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x85, 0x77, 0x6F, 0x72, 0x6C, 0x64>> """ @spec encode_list(list(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_list(list, bolt_version), do: EncoderHelper.call_encode(:list, list, bolt_version) @doc """ Encode a map into Bolt binary format. Note that Elixir structs are converted to map for encoding purpose. Encoding: `Marker` `Size` `Content` with | Marker | Size | Max map size | |--------|------|---------------| | `0xA0`..`0xAF` | None (contained in marker) | 15 entries | | `0xD8` | 8-bit integer | 255 entries | | `0xD9` | 16-bit integer | 65_535 entries | | `0xDA` | 32-bit integer | 4_294_967_295 entries | ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_map(%{id: 345, value: "hello world"}, 1)) <<0xA2, 0x82, 0x69, 0x64, 0xC9, 0x1, 0x59, 0x85, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x8B, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64>> """ @spec encode_map(map(), integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_map(map, bolt_version), do: EncoderHelper.call_encode(:map, map, bolt_version) @doc """ Encode a struct into Bolt binary format. This concerns Bolt Structs as defined in [](). Elixir structs are just converted to regular maps before encoding Encoding: `Marker` `Size` `Signature` `Content` with | Marker | Size | Max structure size | |--------|------|---------------| | `0xB0`..`0xBF` | None (contained in marker) | 15 fields | | `0xDC` | 8-bit integer | 255 fields | | `0xDD` | 16-bit integer | 65_535 fields | ## Example iex> alias Bolt.Sips.Internals.PackStream.EncoderV1 iex> :erlang.iolist_to_binary(EncoderV1.encode_struct({0x01, ["two", "params"]}, 1)) <<0xB2, 0x1, 0x83, 0x74, 0x77, 0x6F, 0x86, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73>> """ @spec encode_struct({integer(), list()}, integer()) :: Bolt.Sips.Internals.PackStream.value() def encode_struct(struct, bolt_version) , do: EncoderHelper.call_encode(:struct, struct, bolt_version) end