anchor.diff:                       {n_val, pos_integer()} |
                        include_context | {include_context, boolean()}.
   
  +%% Server-side type<->module mappings
  +-type type_mappings() :: [{embedded_type(), module()}].
  +
   
   %% @doc Decodes a MapField message into a tuple of name and type.
   -spec decode_map_field(#mapfield{}) -> map_field().
  -decode_map_field(#mapfield{name=Name,type=Type}) ->
  -    {Name, decode_type(Type)}.
  +decode_map_field(MapField) ->
  +    decode_map_field(MapField, []).
  +
  +%% @doc Decodes a MapField message into a tuple of name and type.
  +-spec decode_map_field(#mapfield{}, type_mappings()) -> map_field().
  +decode_map_field(#mapfield{name=Name,type=Type}, Mods) ->
  +    {Name, decode_type(Type, Mods)}.
   
   %% @doc Encodes a tuple of name and type into a MapField message.
   -spec encode_map_field(map_field()) -> #mapfield{}.
  -encode_map_field({Name, Type}) ->
  -    #mapfield{name=Name, type=encode_type(Type)}.
  +encode_map_field(Field) ->
  +    encode_map_field(Field, []).
  +
  +%% @doc Encodes a tuple of name and type into a MapField message,
  +%% using the given type mappings.
  +-spec encode_map_field(map_field(), type_mappings()) -> #mapfield{}.
  +encode_map_field({Name, Type}, Mods) ->
  +    #mapfield{name=Name, type=encode_type(Type, Mods)}.
   
   %% @doc Decodes an MapEntry message into a tuple of field and value.
   -spec decode_map_entry(#mapentry{}) -> map_entry().
  -decode_map_entry(#mapentry{field=#mapfield{type='COUNTER'}=Field, counter_value=Val}) ->
  -    {decode_map_field(Field), Val};
  -decode_map_entry(#mapentry{field=#mapfield{type='SET'}=Field, set_value=Val}) ->
  -    {decode_map_field(Field), Val};
  -decode_map_entry(#mapentry{field=#mapfield{type='REGISTER'}=Field, register_value=Val}) ->
  -    {decode_map_field(Field), Val};
  -decode_map_entry(#mapentry{field=#mapfield{type='FLAG'}=Field, flag_value=Val}) ->
  -    {decode_map_field(Field), Val}.
  +decode_map_entry(Entry) ->
  +    decode_map_entry(Entry, []).
  +
  +%% @doc Decodes an MapEntry message into a tuple of field and value,
  +%% using the given type mappings.
  +-spec decode_map_entry(#mapentry{}, type_mappings()) -> map_entry().
  +decode_map_entry(#mapentry{field=#mapfield{type='COUNTER'}=Field, counter_value=Val}, Mods) ->
  +    {decode_map_field(Field, Mods), Val};
  +decode_map_entry(#mapentry{field=#mapfield{type='SET'}=Field, set_value=Val}, Mods) ->
  +    {decode_map_field(Field, Mods), Val};
  +decode_map_entry(#mapentry{field=#mapfield{type='REGISTER'}=Field, register_value=Val}, Mods) ->
  +    {decode_map_field(Field, Mods), Val};
  +decode_map_entry(#mapentry{field=#mapfield{type='FLAG'}=Field, flag_value=Val}, Mods) ->
  +    {decode_map_field(Field, Mods), Val}.
   
   %% @doc Encodes a tuple of field and value into a MapEntry message.
   -spec encode_map_entry(map_entry()) -> #mapentry{}.
  -encode_map_entry({{Name, counter=Type}, Value}) when is_integer(Value) ->
  +encode_map_entry(Entry) ->
  +    encode_map_entry(Entry, []).
  +
  +%% @doc Encodes a tuple of field and value into a MapEntry message.
  +-spec encode_map_entry(map_entry(), type_mappings()) -> #mapentry{}.
  +encode_map_entry({{Name, counter=Type}, Value}, _Mods) when is_integer(Value) ->
       #mapentry{field=encode_map_field({Name, Type}), counter_value=Value};
  -encode_map_entry({{Name, set=Type}, Value}) when is_list(Value) ->
  +encode_map_entry({{Name, set=Type}, Value}, _Mods) when is_list(Value) ->
       #mapentry{field=encode_map_field({Name, Type}), set_value=Value};
  -encode_map_entry({{Name, register=Type}, Value}) when is_binary(Value) ->
  +encode_map_entry({{Name, register=Type}, Value}, _Mods) when is_binary(Value) ->
       #mapentry{field=encode_map_field({Name, Type}), register_value=Value};
  -encode_map_entry({{Name, flag=Type}, Value}) when is_boolean(Value) ->
  -    #mapentry{field=encode_map_field({Name, Type}), flag_value=Value}.
  -
  +encode_map_entry({{Name, flag=Type}, Value}, _Mods) when is_boolean(Value) ->
  +    #mapentry{field=encode_map_field({Name, Type}), flag_value=Value};
  +encode_map_entry({{Name, Type}, Value}, Mods) ->
  +    %% We reach this clause if the type is not in the shortname yet,
  +    %% but is a module name.
  +    case lists:keyfind(Type, 2, Mods) of
  +        false ->
  +            %% If you don't have a mapping, we can't encode it.
  +            erlang:error(badarg, [{{Name,Type},Value}, Mods]);
  +        {AtomType, Type} ->
  +            encode_map_entry({{Name,AtomType}, Value}, Mods)
  +    end.
   
   %% @doc Encodes a fetch request into a DtFetch message.
   -spec encode_fetch_request({binary(), binary()}, binary()) -> #dtfetchreq{}.
  
positive.code:          encode_fetch_request/3,
           decode_fetch_response/1,
           encode_fetch_response/3,
           encode_update_request/4,
           encode_update_request/5,
           decode_operation/1,
           decode_update_response/3,
           encode_update_response/4
          ]).
  
  -import(riak_pb_kv_codec, [encode_quorum/1]).
  
negative.code: decode_type('REGISTER') -> register;
  decode_type('FLAG')     -> flag;
  decode_type('MAP')      -> map.
  
  %% @doc Encodes an atom type into the PB message equivalent, using the
  %% pass mappings to convert module names into shortnames.
  -spec encode_type(atom(), type_mappings()) -> atom().
  encode_type(TypeOrMod, Mods) ->
      case lists:keyfind(TypeOrMod, 2, Mods) of
          {AtomType, TypeOrMod} ->
              encode_type(AtomType);
          false ->
              encode_type(TypeOrMod)
      end.
  
  %% @doc Encodes an atom type name into the PB message equivalent.
  -spec encode_type(atom()) -> atom().
  