From 46657387a5924724dc99480725f3802bdc4197db Mon Sep 17 00:00:00 2001 From: Andrea Leopardi Date: Fri, 6 Dec 2019 01:00:45 +0100 Subject: [PATCH 1/3] Raise on non-existing fields in Protobuf.Builder.new/2 --- lib/protobuf/builder.ex | 2 +- test/protobuf/builder_test.exs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/protobuf/builder.ex b/lib/protobuf/builder.ex index 4a9ab9d3..1bb6dea6 100644 --- a/lib/protobuf/builder.ex +++ b/lib/protobuf/builder.ex @@ -9,7 +9,7 @@ defmodule Protobuf.Builder do attrs _ -> - msg = struct(mod.__default_struct__(), attrs) + msg = struct!(mod.__default_struct__(), attrs) props = mod.__message_props__() Enum.reduce(props.embedded_fields, msg, fn k, acc -> diff --git a/test/protobuf/builder_test.exs b/test/protobuf/builder_test.exs index f5c2425d..6b74208e 100644 --- a/test/protobuf/builder_test.exs +++ b/test/protobuf/builder_test.exs @@ -49,4 +49,10 @@ defmodule Protobuf.BuilderTest do msg = %Foo{} assert msg == Foo.new(msg) end + + test "new/2 raises for fields that don't exist in the schema" do + assert_raise KeyError, fn -> + Foo.new(nonexisting_field: "foo") + end + end end From 4b4353609c8974efdbef2cd0aad5d35e39bc4d8f Mon Sep 17 00:00:00 2001 From: Andrea Leopardi Date: Sat, 21 Dec 2019 15:11:07 +0100 Subject: [PATCH 2/3] Use new!/2 --- lib/protobuf/builder.ex | 59 ++++++++++++++++++++-------------- test/protobuf/builder_test.exs | 2 +- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/protobuf/builder.ex b/lib/protobuf/builder.ex index 1bb6dea6..dfb401e1 100644 --- a/lib/protobuf/builder.ex +++ b/lib/protobuf/builder.ex @@ -4,13 +4,46 @@ defmodule Protobuf.Builder do end def new(mod, attrs) do + new_maybe_strict(mod, attrs, _strict? = false) + end + + def new!(mod, attrs) do + new_maybe_strict(mod, attrs, _strict? = true) + end + + def field_default(_, %{default: default}) when not is_nil(default), do: default + def field_default(_, %{repeated?: true}), do: [] + def field_default(_, %{map?: true}), do: %{} + def field_default(:proto3, props), do: type_default(props.type) + def field_default(_, _), do: nil + + def type_default(:int32), do: 0 + def type_default(:int64), do: 0 + def type_default(:uint32), do: 0 + def type_default(:uint64), do: 0 + def type_default(:sint32), do: 0 + def type_default(:sint64), do: 0 + def type_default(:bool), do: false + def type_default({:enum, _}), do: 0 + def type_default(:fixed32), do: 0 + def type_default(:sfixed32), do: 0 + def type_default(:fixed64), do: 0 + def type_default(:sfixed64), do: 0 + def type_default(:float), do: 0.0 + def type_default(:double), do: 0.0 + def type_default(:bytes), do: <<>> + def type_default(:string), do: "" + def type_default(_), do: nil + + defp new_maybe_strict(mod, attrs, strict?) do case attrs do %{__struct__: _} -> attrs _ -> - msg = struct!(mod.__default_struct__(), attrs) props = mod.__message_props__() + default_struct = mod.__default_struct__() + msg = if strict?, do: struct!(default_struct, attrs), else: struct(default_struct, attrs) Enum.reduce(props.embedded_fields, msg, fn k, acc -> case msg do @@ -36,28 +69,4 @@ defmodule Protobuf.Builder do end) end end - - def field_default(_, %{default: default}) when not is_nil(default), do: default - def field_default(_, %{repeated?: true}), do: [] - def field_default(_, %{map?: true}), do: %{} - def field_default(:proto3, props), do: type_default(props.type) - def field_default(_, _), do: nil - - def type_default(:int32), do: 0 - def type_default(:int64), do: 0 - def type_default(:uint32), do: 0 - def type_default(:uint64), do: 0 - def type_default(:sint32), do: 0 - def type_default(:sint64), do: 0 - def type_default(:bool), do: false - def type_default({:enum, _}), do: 0 - def type_default(:fixed32), do: 0 - def type_default(:sfixed32), do: 0 - def type_default(:fixed64), do: 0 - def type_default(:sfixed64), do: 0 - def type_default(:float), do: 0.0 - def type_default(:double), do: 0.0 - def type_default(:bytes), do: <<>> - def type_default(:string), do: "" - def type_default(_), do: nil end diff --git a/test/protobuf/builder_test.exs b/test/protobuf/builder_test.exs index 6b74208e..2104bb79 100644 --- a/test/protobuf/builder_test.exs +++ b/test/protobuf/builder_test.exs @@ -50,7 +50,7 @@ defmodule Protobuf.BuilderTest do assert msg == Foo.new(msg) end - test "new/2 raises for fields that don't exist in the schema" do + test "new!/2 raises for fields that don't exist in the schema" do assert_raise KeyError, fn -> Foo.new(nonexisting_field: "foo") end From d395da0682467269bc08b22dcaf54811a6230c2c Mon Sep 17 00:00:00 2001 From: Andrea Leopardi Date: Mon, 23 Dec 2019 09:04:58 +0100 Subject: [PATCH 3/3] Generate new! when "use Protobuf" is called --- lib/protobuf.ex | 4 ++++ test/protobuf/builder_test.exs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/protobuf.ex b/lib/protobuf.ex index 464bffe6..5f3f4770 100644 --- a/lib/protobuf.ex +++ b/lib/protobuf.ex @@ -16,6 +16,10 @@ defmodule Protobuf do def new(attrs) do Protobuf.Builder.new(__MODULE__, attrs) end + + def new!(attrs) do + Protobuf.Builder.new!(__MODULE__, attrs) + end end end diff --git a/test/protobuf/builder_test.exs b/test/protobuf/builder_test.exs index 2104bb79..3a540832 100644 --- a/test/protobuf/builder_test.exs +++ b/test/protobuf/builder_test.exs @@ -52,7 +52,7 @@ defmodule Protobuf.BuilderTest do test "new!/2 raises for fields that don't exist in the schema" do assert_raise KeyError, fn -> - Foo.new(nonexisting_field: "foo") + Foo.new!(nonexisting_field: "foo") end end end