anchor.diff:       end
        || Field <- MsgDef].
   
  -field_encode_expr(MsgName, #?gpb_field{}=Field, FVar, PrevBVar) ->
  +zip_for_non_opt_fields([#?gpb_field{name=FName, occurrence=Occurrence} | FRest],
  +                       [Elem | ERest]) ->
  +    case Occurrence of
  +        optional -> zip_for_non_opt_fields(FRest, ERest);
  +        required -> [{FName, Elem} | zip_for_non_opt_fields(FRest, ERest)];
  +        repeated -> [{FName, Elem} | zip_for_non_opt_fields(FRest, ERest)]
  +    end;
  +zip_for_non_opt_fields([#gpb_oneof{} | FRest], [_Elem | ERest]) ->
  +    zip_for_non_opt_fields(FRest, ERest);
  +zip_for_non_opt_fields([], []) ->
  +    [].
  +
  +field_encode_expr(MsgName, MsgVar, #?gpb_field{name=FName}=Field, FVar,
  +                  PrevBVar, Opts)->
       FEncoder = mk_field_encode_fn_name(MsgName, Field),
       #?gpb_field{occurrence=Occurrence, type=Type, fnum=FNum}=Field,
  -    Transforms = [replace_tree('<F>', FVar),
  +    Transforms = [replace_term('fieldname', FName),
  +                  replace_tree('<F>', FVar),
                     replace_term('<enc>', FEncoder),
                     replace_tree('<Bin>', PrevBVar),
                     splice_trees('<Key>', key_to_binary_fields(FNum, Type))],
       case Occurrence of
           optional ->
  -            ?expr(
  -               if '<F>' == undefined -> '<Bin>';
  -                  true -> '<enc>'('<F>', <<'<Bin>'/binary, '<Key>'>>)
  -               end,
  -               Transforms);
  +            case get_mapping_and_unset_by_opts(Opts) of
  +                X when X == records;
  +                       X == {maps, present_undefined} ->
  +                    ?expr(
  +                       if '<F>' == undefined -> '<Bin>';
  +                          true -> '<enc>'('<F>', <<'<Bin>'/binary, '<Key>'>>)
  +                       end,
  +                       Transforms);
  +                {maps, omitted} ->
  +                    ?expr(
  +                       case maps:find('fieldname', 'M') of
  +                           error ->
  +                               '<Bin>';
  +                           {ok, '<F>'} ->
  +                               '<enc>'('<F>', <<'<Bin>'/binary, '<Key>'>>)
  +                       end,
  +                       [replace_tree('M', MsgVar) | Transforms])
  +            end;
           repeated ->
               ?expr(
                  if '<F>' == [] -> '<Bin>';
  
positive.code:                '<enc>'('<F>', <<'<Bin>'/binary, '<Key>'>>),
                 Transforms)
      end;
  field_encode_expr(MsgName, #gpb_oneof{fields=OFields}, FVar, PrevBVar) ->
      OFVar = prefix_var("O", FVar),
      OneofClauseTransform =
          repeat_clauses(
            '<oneof...>',
            [begin
                 MatchPattern = ?expr({'<oneof-name>', '<OF>'},
                                      [replace_term('<oneof-name>', Name),
                                       replace_tree('<OF>', OFVar)]),
                 %% undefined is already handled, we have a match,
                 %% the field occurs, as if it had been required
                 OField2 = OField#?gpb_field{occurrence=required},
                 EncExpr = field_encode_expr(MsgName, OField2, OFVar, PrevBVar),
                 [replace_tree('<oneof...>', MatchPattern),
                  replace_tree('<expr>', EncExpr)]
             end
             || #?gpb_field{name=Name}=OField <- OFields]),
      ?expr(case '<F>' of
                undefined    -> '<Bin>';
                '<oneof...>' -> '<expr>'
            end,
            [replace_tree('<F>', FVar),
             replace_tree('<Bin>', PrevBVar),
             OneofClauseTransform]).
  %%).
  
  mk_field_encode_fn_name(MsgName, #?gpb_field{occurrence=repeated, name=FName}) ->
      mk_fn(e_field_, MsgName, FName);
  
negative.code:         true  -> maps
      end.
  
  get_mapping_and_unset_by_opts(Opts) ->
      case get_records_or_maps_by_opts(Opts) of
          records ->
              records;
          maps ->
              Default = present_undefined,
              {maps, proplists:get_value(maps_unset_optional, Opts, Default)}
      end.
  
  %% records
  record_match(RName, Fields) -> record_create_or_match(RName, Fields).
  