anchor.diff:       f("    ~p(~s, 0, 0, NewMsg).~n",
          [mk_fn(d_read_field_def_, MsgName), RestVar])].
   
  +%% -> {FValueCode, Rest2Var}
  +%% Produce code for setting a variable, FValueVar, depending on the
  +%% varint type Type, for the raw unpacked expr, BValueExpr.
  +%%
  +%% The initial RestVar is the name of the variable holding the rest
  +%% of the bytes. An updated -- or the same -- such variable is returned.
  +%%
  +%% Indent the code to Indent spaces.
  +%% The resulting code contains one or more statements that ends with comma.
  +mk_unpack_vi(Indent, FValueVar, BValueExpr, Type, RestVar) ->
  +    Rest2Var = RestVar ++ "2",
  +    case Type of
  +        sint32 ->
  +            {[indent(Indent, f("BValue = ~s,~n", [BValueExpr])),
  +              indent(Indent, f("~s = ~s,~n",
  +                               [FValueVar,
  +                                fmt_decode_zigzag(Indent+7, "BValue")]))],
  +             RestVar};
  +        sint64 ->
  +            {[indent(Indent, f("BValue = ~s,~n", [BValueExpr])),
  +              indent(Indent, f("~s = ~s,~n",
  +                               [FValueVar,
  +                                fmt_decode_zigzag(Indent+7, "BValue")]))],
  +             RestVar};
  +        int32 ->
  +            {indent(Indent, f("~s,~n",
  +                              [fmt_uint_to_int(BValueExpr, FValueVar, 32)])),
  +             RestVar};
  +        int64 ->
  +            {indent(Indent, f("~s,~n",
  +                              [fmt_uint_to_int(BValueExpr, FValueVar, 64)])),
  +             RestVar};
  +        uint32 ->
  +            {indent(Indent, f("~s = ~s,~n", [FValueVar, BValueExpr])),
  +             RestVar};
  +        uint64 ->
  +            {indent(Indent, f("~s = ~s,~n", [FValueVar, BValueExpr])),
  +             RestVar};
  +        bool ->
  +            {indent(Indent, f("~s = ((~s) =/= 0),~n", [FValueVar, BValueExpr])),
  +             RestVar};
  +        {enum, EnumName} ->
  +            {[indent(Indent, f("~s,~n",
  +                               [fmt_uint_to_int(BValueExpr, "EnumValue", 32)])),
  +              indent(Indent, f("~s = ~p(EnumValue),~n",
  +                               [FValueVar, mk_fn(d_enum_, EnumName)]))],
  +             RestVar};
  +        string ->
  +            {[indent(Indent, f("Len = ~s,~n", [BValueExpr])),
  +              indent(Indent, f("<<Utf8:Len/binary, ~s/binary>> = ~s,~n",
  +                               [Rest2Var, RestVar])),
  +              indent(Indent, f("~s = unicode:characters_to_list("
  +                               "Utf8,unicode),~n",
  +                               [FValueVar]))],
  +             Rest2Var};
  +        bytes ->
  +            {[indent(Indent, f("Len = ~s,~n", [BValueExpr])),
  +              indent(Indent, f("<<~s:Len/binary, ~s/binary>> = ~s,~n",
  +                               [FValueVar, Rest2Var, RestVar]))],
  +             Rest2Var};
  +        {msg,Msg2Name} ->
  +            {[indent(Indent, f("Len = ~s,~n", [BValueExpr])),
  +              indent(Indent, f("<<MsgBytes:Len/binary, ~s/binary>> = ~s,~n",
  +                               [Rest2Var, RestVar])),
  +              indent(Indent, f("~s = decode_msg(MsgBytes, ~p),~n",
  +                               [FValueVar, Msg2Name]))],
  +             Rest2Var}
  +    end.
  +
  +
  +
   fmt_uint_to_int(SrcStr, ResultVar, NumBits) ->
       f("<<~s:~w/signed-native>> = <<(~s):~p/unsigned-native>>",
         [ResultVar, NumBits, SrcStr, NumBits]).
  
positive.code:      f("    ~p(Rest, 0, 0, NewMsg).~n",
         [mk_fn(d_read_field_def_, MsgName)])].
  
  
  format_msg_decoder_reverse_toplevel(MsgName, MsgDef) ->
      MsgNameQLen = iolist_size(f("~p", [MsgName])),
  
negative.code:         mk_fn(d_reverse_toplevel_fields_, MsgName)])].
  
  format_read_field_cases(MsgName, MsgDef) ->
      [indent(8, f("~p -> ~p(Rest~sMsg);~n",
                   [FNum, mk_fn(d_field_, MsgName, FName),
                    case mk_field_decoder_vi_params(FieldDef) of
                        ""     -> [", "];
                        Params -> [", ", Params, ", "]
                    end]))
       || #field{fnum=FNum, name=FName}=FieldDef <- MsgDef].
  
  mk_field_decoder_vi_params(#field{type=Type}) ->
      case Type of
          sint32   -> "0, 0"; %% varint-based
          sint64   -> "0, 0"; %% varint-based
  