anchor.diff:  
   %% @doc Decodes a SetOp message into a set operation.
   -spec decode_set_op(#setop{}) -> set_op().
  +decode_set_op(#setop{adds=A, removes=[]}) ->
  +    {add_all, A};
  +decode_set_op(#setop{adds=[], removes=R}) ->
  +    {remove_all, R};
   decode_set_op(#setop{adds=A, removes=R}) ->
  -    {update, A, R}.
  +    {update, [{add_all, A}, {remove_all, R}]}.
   
   %% @doc Encodes a set operation into a SetOp message.
   -spec encode_set_op(set_op()) -> #setop{}.
  -encode_set_op({Op, Member}) when is_binary(Member) ->
  -    encode_set_op({Op, [Member]});
  -encode_set_op({add, Members}) when is_list(Members) ->
  -    #setop{adds=Members};
  -encode_set_op({remove, Members}) when is_list(Members) ->
  -    #setop{removes=Members};
  -encode_set_op({update, Adds, Removes}) when is_list(Adds), is_list(Removes) ->
  -    #setop{adds=Adds, removes=Removes}.
  +encode_set_op({update, Ops}) when is_list(Ops) ->
  +    lists:foldr(fun encode_set_update/2, #setop{}, Ops);
  +encode_set_op({C, _}=Op) when add == C; add_all == C;
  +                              remove == C; remove_all == C->
  +    encode_set_op({update, [Op]}).
  +
  +%% @doc Folds a set update into the SetOp message.
  +-spec encode_set_update(simple_set_op(), #setop{}) -> #setop{}.
  +encode_set_update({add, Member}, #setop{adds=A}=S) when is_binary(Member) ->
  +    S#setop{adds=[Member|A]};
  +encode_set_update({add_all, Members}, #setop{adds=A}=S) when is_list(Members) ->
  +    S#setop{adds=Members++A};
  +encode_set_update({remove, Member}, #setop{removes=R}=S) when is_binary(Member) ->
  +    S#setop{removes=[Member|R]};
  +encode_set_update({remove_all, Members}, #setop{removes=R}=S) when is_list(Members) ->
  +    S#setop{removes=Members++R}.
  +
   
   %% @doc Decodes a operation name from a PB message into an atom.
   -spec decode_flag_op(atom()) -> atom().
  
positive.code: 
  %% @doc Encodes a map operation into a MapOp message.
  -spec encode_map_op(map_op()) -> #mapop{}.
  encode_map_op({update, Adds, Removes, Updates}) ->
      #mapop{
         adds=[ encode_map_field(A) || Adds /= undefined, A <- Adds ],
         removes=[ encode_map_field(R) || Removes /= undefined, R <- Removes ],
         updates=[ encode_map_update(K,O) || Updates /= undefined,
                                             {K, O} <- Updates ]}.
  
  decode_map_op(#mapop{adds=Adds, removes=Removes, updates=Updates}, Mods) ->
      {update, 
       [ decode_map_field(A, Mods) || A <- Adds ],
       [ decode_map_field(R, Mods) || R <- Removes ],
       [ decode_map_update(U, Mods) || U <- Updates ]}.
  
  %% @doc Decodes a DtOperation message into a datatype-specific operation.
  -spec decode_operation(#dtop{}) -> toplevel_op().
  
negative.code: encode_update_response(set, Value, Key, Context, _Mods) ->
      #dtupdateresp{key=Key, context=Context, set_value=Value};
  encode_update_response(map, Value, Key, Context, Mods) when is_list(Value) ->
      #dtupdateresp{key=Key, context=Context,
                    map_value=[ encode_map_entry(Entry, Mods) || Value /= undefined,
                                                                 Entry <- Value ]}.
  