     end
   end
 
-  defp empty_val?(nil), do: true
-  defp empty_val?(false), do: true
-  defp empty_val?(0), do: true
-  defp empty_val?(0.0), do: true
-  defp empty_val?(""), do: true
-  defp empty_val?([]), do: true
-  defp empty_val?(v) when map_size(v) == 0, do: true
-  defp empty_val?(_) do
-    false
-  end
-
   defp is_enum_default({_, type}, v) when is_atom(v), do: type.value(v) == 0
   defp is_enum_default({_, _}, v) when is_integer(v), do: v == 0
   defp is_enum_default({_, _}, _), do: false

      # so that oneof {:atom, v} can be encoded
      encoded = encode(type, v, [])
      byte_size = byte_size(encoded)
      [fnum, [encode_varint(byte_size), encoded]]
    end)
  end

  def encode_field(:packed, val, %{type: type, encoded_fnum: fnum}) do
    encoded = Enum.map(val, fn v -> encode_type(type, v) end)
    byte_size = IO.iodata_length(encoded)
    [fnum, [encode_varint(byte_size), encoded]]
  end

  @spec class_field(map) :: atom

  @spec encode(struct, keyword) :: iodata
  def encode(%mod{} = struct, opts \\ []) do
    res = encode!(struct, mod.__message_props__())

    case Keyword.fetch(opts, :iolist) do
      {:ok, true} -> res
