Packages
protox
1.7.5
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/field_mask.ex
# This implementation has been developed by making the conformance tests happy. However, I'm not sure
# they cover everything, and the specification is a little light on details.
# https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#json-encoding-of-field-masks
defmodule Protox.Google.Protobuf.FieldMask do
@moduledoc false
use Protox.Define,
enums: [],
messages: [
%Protox.Message{
name: Google.Protobuf.FieldMask,
syntax: :proto3,
fields: [
Protox.Field.new!(
kind: :unpacked,
label: :repeated,
name: :paths,
tag: 1,
type: :string
)
]
}
]
end
defimpl Protox.JsonMessageDecoder, for: Google.Protobuf.FieldMask do
def decode_message(_initial_message, nil), do: nil
def decode_message(initial_message, json) do
if String.contains?(json, "_") do
raise Protox.JsonDecodingError.new(
"field mask has an invalid format (it contains an \"_\")"
)
end
paths =
json
|> String.split(",")
|> Enum.map(&Macro.underscore/1)
|> Enum.reject(fn str -> String.length(str) == 0 end)
struct!(initial_message, paths: paths)
end
end
defimpl Protox.JsonMessageEncoder, for: Google.Protobuf.FieldMask do
def encode_message(msg, json_encode) do
case check_paths(msg.paths) do
:ok ->
msg.paths
|> Enum.map_join(",", &lower_camel_case/1)
|> json_encode.()
:error ->
raise Protox.JsonEncodingError.new("#{msg.__struct__}.paths is invalid")
end
end
defp lower_camel_case(string) do
string
|> String.split(".")
|> Enum.map_join(".", fn str ->
<<first, rest::binary>> = Macro.camelize(str)
<<String.downcase(<<first>>, :ascii)::binary, rest::binary>>
end)
end
defp check_paths(paths) do
res =
Enum.any?(paths, fn path ->
with false <- has_too_many_underscores?(path),
false <- has_a_number_in_path_component?(path),
false <- has_camel_cased_components?(path) do
false
else
_ ->
true
end
end)
if res do
:error
else
:ok
end
end
defp has_too_many_underscores?(path) do
String.contains?(path, "__")
end
defp has_a_number_in_path_component?(path) do
path
|> String.split("_")
|> Enum.any?(fn str ->
String.starts_with?(str, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
end)
end
defp has_camel_cased_components?(path) do
path
|> String.split("_")
|> Enum.any?(fn str -> str == lower_camel_case(str) and not (str == String.downcase(str)) end)
end
end