anchor.diff:          []    -> undefined
       end.
   
  -defs_to_msgtype(Defs) ->
  +defs_to_msgtype(Defs, MapTypesToPseudoMsgNames, MapPseudoMsgs) ->
       AllOneofs = get_all_oneofs(Defs),
       %% There is a slight bit of mismatch here: the DescriptorProto
       %% contains fields for `nested_type' and `enum_type', and defines
  
positive.code:         options         = undefined,
          oneof_decl      = oneof_decl(AllOneofs)
         }
       || {{msg,MsgName}, Fields} <- Defs].
  
  field_defs_to_mgstype_fields(Fields, AllOneofs) ->
      lists:append([field_def_to_msgtype_field(Field, AllOneofs)
                    || Field <- Fields]).
  
  field_def_to_msgtype_field(#?gpb_field{name=FName,
  
negative.code: oneof_decl(AllOneofs) ->
      [#'OneofDescriptorProto'{name=atom_to_ustring(Name)} || Name <- AllOneofs].
  
  compute_map_field_pseudo_msgs(Defs) ->
      AllMapTypes = find_all_map_types(Defs),
      MapTypePseudoMsgNames = invent_unused_msg_names(Defs, length(AllMapTypes)),
      ToName = lists:zip(AllMapTypes, MapTypePseudoMsgNames),
      ToMapT = lists:zip(MapTypePseudoMsgNames, AllMapTypes),
      {dict:from_list(ToName),
       [{{msg, Name}, gpb:map_item_pseudo_fields(KeyType, ValueType)}
        || {Name, {map, KeyType, ValueType}} <- ToMapT]}.
  
  find_all_map_types(Defs) ->
      lists:sort(
        sets:to_list(
          lists:foldl(
            fun({{msg,_}, Fields}, Acc) ->
                    lists:foldl(fun(#?gpb_field{type={map,_,_}=T}, Acc2) ->
                                        sets:add_element(T, Acc2);
                                   (_, Acc2) ->
                                        Acc2
                                end,
                                Acc,
                                Fields);
               (_, Acc) ->
                    Acc
            end,
            sets:new(),
            Defs))).
  
  invent_unused_msg_names(Defs, N) ->
      AllMsgNames = sets:from_list([Name || {{msg,Name}, _Fields} <- Defs]),
      Base = "MapFieldEntry",
      invent_unused_msg_names_aux(Base, 1, N, AllMsgNames).
  
  invent_unused_msg_names_aux(Base, I, N, AllMsgNames) ->
      NewNames = sets:from_list([list_to_atom(?ff("~s_~w_~w", [Base, I, J]))
                                 || J <- lists:seq(1,N)]),
      case sets:is_disjoint(NewNames, AllMsgNames) of
          true  -> sets:to_list(NewNames);
          false -> invent_unused_msg_names_aux(Base, I+1, N, AllMsgNames)
      end.
  
  atom_to_ustring(A) ->
      Utf8Str = atom_to_list(A),
      unicode:characters_to_list(list_to_binary(Utf8Str), utf8).
  