@@ -121,8 +121,8 @@ defmodule Protobuf.JSON do
121
121
"""
122
122
@ spec encode! ( struct , [ encode_opt ] ) :: String . t ( ) | no_return
123
123
def encode! ( struct , opts \\ [ ] ) do
124
- case encode ( struct , opts ) do
125
- { :ok , json } -> json
124
+ case encode_to_iodata ( struct , opts ) do
125
+ { :ok , iodata } -> IO . iodata_to_binary ( iodata )
126
126
{ :error , error } -> raise error
127
127
end
128
128
end
@@ -169,9 +169,41 @@ defmodule Protobuf.JSON do
169
169
"""
170
170
@ spec encode ( struct , [ encode_opt ] ) ::
171
171
{ :ok , String . t ( ) } | { :error , EncodeError . t ( ) | Exception . t ( ) }
172
- def encode ( % _ { } = struct , opts \\ [ ] ) when is_list ( opts ) do
172
+ def encode ( struct , opts \\ [ ] ) when is_list ( opts ) do
173
+ case encode_to_iodata ( struct , opts ) do
174
+ { :ok , iodata } -> { :ok , IO . iodata_to_binary ( iodata ) }
175
+ { :error , error } -> { :error , error }
176
+ end
177
+ end
178
+
179
+ @ doc """
180
+ Similar to `encode!/2`, but returns iodata
181
+
182
+ See `encode_to_iodata/2` for more information about when this function should
183
+ be preferred over `encode!/2`.
184
+ """
185
+ @ spec encode_to_iodata! ( struct , [ encode_opt ] ) :: iodata ( )
186
+ def encode_to_iodata! ( struct , opts \\ [ ] ) when is_list ( opts ) do
187
+ case encode_to_iodata ( struct , opts ) do
188
+ { :ok , iodata } -> iodata
189
+ { :error , error } -> raise error
190
+ end
191
+ end
192
+
193
+ @ doc """
194
+ Similar to `encode/2`, but returns iodata
195
+
196
+ This function should be preferred to encode/2, if the generated JSON will be
197
+ handed over to one of the IO functions or sent over the socket. The Erlang
198
+ runtime is able to leverage vectorised writes and avoid allocating a continuous
199
+ buffer for the whole resulting string, lowering memory use and increasing
200
+ performance.
201
+ """
202
+ @ spec encode_to_iodata ( struct , [ encode_opt ] ) ::
203
+ { :ok , iodata ( ) } | { :error , EncodeError . t ( ) | Exception . t ( ) }
204
+ def encode_to_iodata ( % _ { } = struct , opts \\ [ ] ) when is_list ( opts ) do
173
205
if jason = load_jason ( ) do
174
- with { :ok , map } <- to_encodable ( struct , opts ) , do: jason . encode ( map )
206
+ with { :ok , map } <- to_encodable ( struct , opts ) , do: jason . encode_to_iodata ( map )
175
207
else
176
208
{ :error , EncodeError . new ( :no_json_lib ) }
177
209
end
0 commit comments