Packages
protox
2.0.3
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
2.0.0-dev
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
retired
1.7.3
1.7.2
1.7.1
1.7.0
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.1
1.1.0
1.0.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.0
0.21.0
0.20.0
0.19.1
0.19.0
0.18.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.2
0.15.1
0.15.0
0.14.0
0.13.0
0.12.1
0.12.0
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.0
0.7.1
0.7.0
A fast, easy to use and 100% conformant Elixir library for Google Protocol Buffers (aka protobuf)
Current section
Files
Jump to
Current section
Files
lib/protox/encode.ex
defmodule Protox.Encode do
@moduledoc false
use Protox.{
Float,
WireTypes
}
import Bitwise
import Protox.Guards
alias Protox.{
Varint,
Zigzag
}
@doc false
@spec make_key_bytes(Protox.Types.tag(), Protox.Types.type()) :: {binary(), non_neg_integer()}
def make_key_bytes(tag, ty) do
Varint.encode(make_key(tag, ty))
end
@doc false
@spec make_key(Protox.Types.tag(), Protox.Types.type()) :: non_neg_integer()
def make_key(tag, ty) when is_primitive_varint(ty), do: tag <<< 3 ||| @wire_varint
def make_key(tag, {:enum, _}), do: tag <<< 3 ||| @wire_varint
def make_key(tag, ty) when is_primitive_fixed64(ty), do: tag <<< 3 ||| @wire_64bits
def make_key(tag, ty) when is_delimited(ty), do: tag <<< 3 ||| @wire_delimited
def make_key(tag, {:message, _}), do: tag <<< 3 ||| @wire_delimited
def make_key(tag, :packed), do: tag <<< 3 ||| @wire_delimited
def make_key(tag, :map_entry), do: tag <<< 3 ||| @wire_delimited
def make_key(tag, ty) when is_primitive_fixed32(ty), do: tag <<< 3 ||| @wire_32bits
@doc false
@spec encode_varint_signed(integer()) :: {binary(), non_neg_integer()}
def encode_varint_signed(value) do
value |> Zigzag.encode() |> Varint.encode()
end
@doc false
@spec encode_varint_64(integer()) :: {binary(), non_neg_integer()}
def encode_varint_64(value) do
<<res::unsigned-native-64>> = <<value::signed-native-64>>
Varint.encode(res)
end
@doc false
@spec encode_varint_32(integer()) :: {binary(), non_neg_integer()}
def encode_varint_32(value) when value < 0 do
encode_varint_64(value)
end
@doc false
def encode_varint_32(value) do
<<res::unsigned-native-32>> = <<value::signed-native-32>>
Varint.encode(res)
end
@doc false
@spec encode_bool(boolean()) :: {binary(), non_neg_integer()}
def encode_bool(false), do: {<<0>>, 1}
def encode_bool(true), do: {<<1>>, 1}
@doc false
@spec encode_int32(integer()) :: {binary(), non_neg_integer()}
def encode_int32(value), do: encode_varint_32(value)
@doc false
@spec encode_int64(integer()) :: {binary(), non_neg_integer()}
def encode_int64(value), do: encode_varint_64(value)
@doc false
@spec encode_sint32(integer()) :: {binary(), non_neg_integer()}
def encode_sint32(value), do: encode_varint_signed(value)
@doc false
@spec encode_sint64(integer()) :: {binary(), non_neg_integer()}
def encode_sint64(value), do: encode_varint_signed(value)
@doc false
@spec encode_uint32(non_neg_integer()) :: {binary(), non_neg_integer()}
def encode_uint32(value), do: encode_varint_32(value)
@doc false
@spec encode_uint64(non_neg_integer()) :: {binary(), non_neg_integer()}
def encode_uint64(value), do: encode_varint_64(value)
@doc false
@spec encode_fixed64(integer()) :: {binary(), non_neg_integer()}
def encode_fixed64(value), do: {<<value::little-64>>, 8}
@doc false
@spec encode_sfixed64(integer()) :: {binary(), non_neg_integer()}
def encode_sfixed64(value), do: {<<value::signed-little-64>>, 8}
@doc false
@spec encode_fixed32(integer()) :: {binary(), non_neg_integer()}
def encode_fixed32(value), do: {<<value::little-32>>, 4}
@doc false
@spec encode_sfixed32(integer()) :: {binary(), non_neg_integer()}
def encode_sfixed32(value), do: {<<value::signed-little-32>>, 4}
@doc false
@spec encode_double(float() | atom()) :: {binary(), non_neg_integer()}
def encode_double(:infinity), do: {@positive_infinity_64, 8}
def encode_double(:"-infinity"), do: {@negative_infinity_64, 8}
def encode_double(:nan), do: {@nan_64, 8}
def encode_double(value), do: {<<value::float-little-64>>, 8}
@doc false
@spec encode_float(float() | atom()) :: {binary(), non_neg_integer()}
def encode_float(:infinity), do: {@positive_infinity_32, 4}
def encode_float(:"-infinity"), do: {@negative_infinity_32, 4}
def encode_float(:nan), do: {@nan_32, 4}
def encode_float(value), do: {<<value::float-little-32>>, 4}
@doc false
@spec encode_enum(integer()) :: {binary(), non_neg_integer()}
def encode_enum(value), do: encode_varint_32(value)
@doc false
@spec encode_string(String.t()) :: {iodata(), non_neg_integer()}
def encode_string(value) do
case Protox.String.validate(value) do
:ok ->
{size_varint, size} = Varint.encode(byte_size(value))
{[size_varint, value], size + byte_size(value)}
{:error, :invalid_utf8} ->
raise ArgumentError, message: "String is not valid UTF-8"
{:error, :too_large} ->
raise ArgumentError, message: "String is too large"
end
end
@doc false
@spec encode_bytes(binary()) :: {iodata(), non_neg_integer()}
def encode_bytes(value) do
{size_varint, size} = Varint.encode(byte_size(value))
{[size_varint, value], size + byte_size(value)}
end
@doc false
@spec encode_message(struct()) :: {iodata(), non_neg_integer()}
def encode_message(value) do
{value_bytes, value_size} = value.__struct__.encode!(value)
{value_size_bytes, value_size_bytes_size} = Varint.encode(value_size)
{[value_size_bytes, value_bytes], value_size + value_size_bytes_size}
end
end