Skip to content

Commit

Permalink
Update to _finish callback return new acc
Browse files Browse the repository at this point in the history
  • Loading branch information
michalmuskala committed Feb 20, 2024
1 parent 5b43d9a commit 064402c
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions eeps/eep-0068.md
Expand Up @@ -145,17 +145,15 @@ API that the decoder will use to produce values from the data it parses.
-type from_binary_fun() :: fun((binary()) -> dynamic()).
-type array_start_fun() :: fun((Acc :: dynamic()) -> ArrayAcc :: dynamic()).
-type array_push_fun() :: fun((Value :: dynamic(), Acc :: dynamic()) -> NewAcc :: dynamic()).
-type array_finish_fun() :: fun((ArrayAcc :: dynamic()) -> dynamic()).
-type array_finish_fun() :: fun((ArrayAcc :: dynamic(), OldAcc :: dynamic()) -> {dynamic(), Acc :: dynamic()}).
-type object_start_fun() :: fun((Acc :: dynamic()) -> ObjectAcc :: dynamic()).
-type object_push_fun() :: fun((Key :: dynamic(), Value :: dynamic(), Acc :: dynamic()) -> NewAcc :: dynamic()).
-type object_finish_fun() :: fun((ObjectAcc :: dynamic()) -> dynamic()).
-type object_finish_fun() :: fun((ObjectAcc :: dynamic(), OldAcc :: dynamic()) -> {dynamic(), Acc :: dynamic()}).

-type decoders() :: #{
empty_array => term(),
array_start => array_start_fun(),
array_push => array_push_fun(),
array_finish => array_finish_fun(),
empty_object => term(),
object_start => object_start_fun(),
object_push => object_push_fun(),
object_finish => object_finish_fun(),
Expand Down Expand Up @@ -183,8 +181,25 @@ Furthermore, this allows the user to only retain parts of the data structure
to achieve results similar to using a streaming SAX-like parser for data
that doesn't fully fit into memory.
The `array_finish` and `object_finish` callbacks are responsible for
restoring the accumulator to continue processing the parent object.
To simplify the case where accumulators are not connected, these
callbacks receive value of the accumulator that was passed to the
corresponding `_start` call.
All the callbacks are optional and have a default value corresponding to the
"simple" API behaviour and using lists as accumulators.
"simple" API behaviour, using lists as accumulators, in particular:
* for `array_start`: `fun(_) -> [] end`
* for `array_push`: `fun(Elem, Acc) -> [Elem | Acc] end`
* for `array_finish`: `fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end`
* for `object_start`: `fun(_) -> [] end`
* for `object_push`: `fun(Key, Value, Acc) -> [{Key, Value} | Acc] end`
* for `object_finish`: `fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end`
* for `float`: `fun erlang:binary_to_float/1`
* for `integer`: `fun erlang:binary_to_integer/1`
* for `string`: `fun (Value) -> Value end`
* for `null`: the atom `null`
### Incomplete data parsing
Expand Down Expand Up @@ -309,21 +324,21 @@ object_start(Acc0) => Acc1
object_push(Str2, Str3, Acc8) => Acc9
object_finish(Acc9) => Obj2
array_push(Obj2, Acc7) => Acc10
array_finish(Acc10) => Arr1
object_push(Arr1, Acc1) => Acc11
array_finish(Acc10, Acc1) => {Arr1, Acc11}
object_push(Arr1, Acc11) => Acc12
string(<<"b">>) => Str4
array_start(Acc11) => Acc12
array_start(Acc12) => Acc13
integer(<<"1">>) => Int1
array_push(Int1, Acc12) => Acc13
array_push(Int1, Acc13) => Acc14
float(<<"2.0">>) => Float1
array_push(Float1, Acc13) => Acc14
array_push(Float1, Acc14) => Acc15
string(<<"three">>) => Str5
array_push(Str5, Acc14) => Acc15
array_finish(Acc15) => Arr2
object_push(Str4, Arr2, Acc11) => Acc16
object_finish(Acc16) => Obj3
array_push(Str5, Acc15) => Acc16
array_finish(Acc16, Acc12) => {Arr2, Acc17}
object_push(Str4, Arr2, Acc17) => Acc18
object_finish(Acc18, Acc0) => {Obj3, Acc19}
% final decode/3 return
{Obj3, Acc16, <<"">>}
{Obj3, Acc19, <<"">>}
```
### Example of a custom encoder
Expand Down

0 comments on commit 064402c

Please sign in to comment.