Packages
protox
1.6.2
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/google/protobuf/duration.ex
defmodule Protox.Google.Protobuf.Duration do
@moduledoc false
use Protox.Define,
enums: [],
messages: [
{
Google.Protobuf.Duration,
:proto3,
[
Protox.Field.new!(
kind: {:scalar, 0},
label: :optional,
name: :seconds,
tag: 1,
type: :int64
),
Protox.Field.new!(
kind: {:scalar, 0},
label: :optional,
name: :nanos,
tag: 2,
type: :int32
)
]
}
]
end
defimpl Protox.JsonMessageDecoder, for: Google.Protobuf.Duration do
def decode_message(_initial_message, nil = _json) do
nil
end
def decode_message(initial_message, json) do
dec = get_decimal(json)
{seconds, nanos} = get_seconds_nanos(dec)
cond do
seconds < -315_576_000_000 ->
raise Protox.JsonDecodingError.new("#{seconds} is < -315_576_000_000")
seconds > 315_576_000_000 ->
raise Protox.JsonDecodingError.new("#{seconds} is > 315_576_000_000")
true ->
struct!(initial_message, seconds: seconds, nanos: nanos)
end
end
# -- Private
defp get_decimal(json) do
case Decimal.parse(json) do
{dec, "s"} -> dec
{_dec, _suffix} -> raise Protox.JsonDecodingError.new("invalid duration format")
:error -> raise Protox.JsonDecodingError.new("invalid duration format")
end
end
defp get_seconds_nanos(dec) do
seconds =
if Decimal.negative?(dec) do
Decimal.round(dec, 0, :ceiling)
else
Decimal.round(dec, 0, :floor)
end
nanos = Decimal.mult(Decimal.sub(dec, seconds), 1_000_000_000)
{Decimal.to_integer(seconds), Decimal.to_integer(nanos)}
end
end
defimpl Protox.JsonMessageEncoder, for: Google.Protobuf.Duration do
def encode_message(msg, json_encode) do
cond do
msg.seconds < -315_576_000_000 ->
raise Protox.JsonEncodingError.new("#{msg.__struct__}.seconds is < -315_576_000_000")
msg.seconds > 315_576_000_000 ->
raise Protox.JsonEncodingError.new("{msg.__struct__}.seconds is > 315_576_000_000")
msg.nanos < -999_999_999 ->
raise Protox.JsonEncodingError.new("{msg.__struct__}.nanos is < -999_999_999")
msg.nanos > 999_999_999 ->
raise Protox.JsonEncodingError.new("{msg.__struct__}.nanos is > 999_999_999")
true ->
duration =
Decimal.add(
Decimal.new(msg.seconds),
Decimal.div(Decimal.new(msg.nanos), Decimal.new(1_000_000_000))
)
digits =
cond do
rem(msg.nanos, 1_000_000_000) == 0 -> 0
rem(msg.nanos, 1_000_000) == 0 -> 3
rem(msg.nanos, 1000) == 0 -> 6
true -> 9
end
json_encode.("#{Decimal.round(duration, digits)}s")
end
end
end