mirror of
https://github.com/valitydev/thrift.git
synced 2024-11-07 10:48:51 +00:00
erlang: Refactor the write paths of the client and protocol
TODO: squash this git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@990980 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3f660a4266
commit
c465799c1b
@ -62,7 +62,7 @@ close(#tclient{protocol=Protocol}) ->
|
||||
%%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
-spec send_function_call(#tclient{}, atom(), list()) -> {#tclient{}, ok | {error, term()}}.
|
||||
send_function_call(Client = #tclient{protocol = Proto,
|
||||
send_function_call(Client = #tclient{protocol = Proto0,
|
||||
service = Service,
|
||||
seqid = SeqId},
|
||||
Function,
|
||||
@ -77,11 +77,11 @@ send_function_call(Client = #tclient{protocol = Proto,
|
||||
Begin = #protocol_message_begin{name = atom_to_list(Function),
|
||||
type = ?tMessageType_CALL,
|
||||
seqid = SeqId},
|
||||
ok = thrift_protocol:write(Proto, Begin),
|
||||
ok = thrift_protocol:write(Proto, {Params, list_to_tuple([Function | Args])}),
|
||||
ok = thrift_protocol:write(Proto, message_end),
|
||||
ok = thrift_protocol:flush_transport(Proto),
|
||||
{Client, ok}
|
||||
{Proto1, ok} = thrift_protocol:write(Proto0, Begin),
|
||||
{Proto2, ok} = thrift_protocol:write(Proto1, {Params, list_to_tuple([Function | Args])}),
|
||||
{Proto3, ok} = thrift_protocol:write(Proto2, message_end),
|
||||
{Proto4, ok} = thrift_protocol:flush_transport(Proto3),
|
||||
{Client#tclient{protocol = Proto4}, ok}
|
||||
end.
|
||||
|
||||
-spec receive_function_result(#tclient{}, atom()) -> {#tclient{}, {ok, term()} | {error, term()}}.
|
||||
|
@ -49,10 +49,11 @@ new(Module, Data) when is_atom(Module) ->
|
||||
{ok, #protocol{module = Module,
|
||||
data = Data}}.
|
||||
|
||||
-spec flush_transport(#protocol{}) -> ok.
|
||||
flush_transport(#protocol{module = Module,
|
||||
data = Data}) ->
|
||||
Module:flush_transport(Data).
|
||||
-spec flush_transport(#protocol{}) -> {#protocol{}, ok}.
|
||||
flush_transport(Proto = #protocol{module = Module,
|
||||
data = Data}) ->
|
||||
{NewData, Result} = Module:flush_transport(Data),
|
||||
{Proto#protocol{data = NewData}, Result}.
|
||||
|
||||
-spec close_transport(#protocol{}) -> ok.
|
||||
close_transport(#protocol{module = Module,
|
||||
@ -292,16 +293,16 @@ skip_list_loop(Proto, Map = #protocol_list_begin{etype = Etype,
|
||||
%%
|
||||
%% Description:
|
||||
%%--------------------------------------------------------------------
|
||||
-spec write(#protocol{}, term()) -> ok | {error, _Reason}.
|
||||
-spec write(#protocol{}, term()) -> {#protocol{}, ok | {error, _Reason}}.
|
||||
|
||||
write(Proto, {{struct, StructDef}, Data})
|
||||
write(Proto0, {{struct, StructDef}, Data})
|
||||
when is_list(StructDef), is_tuple(Data), length(StructDef) == size(Data) - 1 ->
|
||||
|
||||
[StructName | Elems] = tuple_to_list(Data),
|
||||
ok = write(Proto, #protocol_struct_begin{name = StructName}),
|
||||
ok = struct_write_loop(Proto, StructDef, Elems),
|
||||
ok = write(Proto, struct_end),
|
||||
ok;
|
||||
{Proto1, ok} = write(Proto0, #protocol_struct_begin{name = StructName}),
|
||||
{Proto2, ok} = struct_write_loop(Proto1, StructDef, Elems),
|
||||
{Proto3, ok} = write(Proto2, struct_end),
|
||||
{Proto3, ok};
|
||||
|
||||
write(Proto, {{struct, {Module, StructureName}}, Data})
|
||||
when is_atom(Module),
|
||||
@ -310,70 +311,74 @@ write(Proto, {{struct, {Module, StructureName}}, Data})
|
||||
StructType = Module:struct_info(StructureName),
|
||||
write(Proto, {Module:struct_info(StructureName), Data});
|
||||
|
||||
write(Proto, {{list, Type}, Data})
|
||||
write(Proto0, {{list, Type}, Data})
|
||||
when is_list(Data) ->
|
||||
ok = write(Proto,
|
||||
{Proto1, ok} = write(Proto0,
|
||||
#protocol_list_begin{
|
||||
etype = term_to_typeid(Type),
|
||||
size = length(Data)
|
||||
}),
|
||||
lists:foreach(fun(Elem) ->
|
||||
ok = write(Proto, {Type, Elem})
|
||||
end,
|
||||
Data),
|
||||
ok = write(Proto, list_end),
|
||||
ok;
|
||||
Proto2 = lists:foldl(fun(Elem, ProtoIn) ->
|
||||
{ProtoOut, ok} = write(ProtoIn, {Type, Elem}),
|
||||
ProtoOut
|
||||
end,
|
||||
Proto1,
|
||||
Data),
|
||||
{Proto3, ok} = write(Proto2, list_end),
|
||||
{Proto3, ok};
|
||||
|
||||
write(Proto, {{map, KeyType, ValType}, Data}) ->
|
||||
ok = write(Proto,
|
||||
#protocol_map_begin{
|
||||
ktype = term_to_typeid(KeyType),
|
||||
vtype = term_to_typeid(ValType),
|
||||
size = dict:size(Data)
|
||||
}),
|
||||
dict:fold(fun(KeyData, ValData, _Acc) ->
|
||||
ok = write(Proto, {KeyType, KeyData}),
|
||||
ok = write(Proto, {ValType, ValData})
|
||||
end,
|
||||
_AccO = ok,
|
||||
Data),
|
||||
ok = write(Proto, map_end),
|
||||
ok;
|
||||
write(Proto0, {{map, KeyType, ValType}, Data}) ->
|
||||
{Proto1, ok} = write(Proto0,
|
||||
#protocol_map_begin{
|
||||
ktype = term_to_typeid(KeyType),
|
||||
vtype = term_to_typeid(ValType),
|
||||
size = dict:size(Data)
|
||||
}),
|
||||
Proto2 = dict:fold(fun(KeyData, ValData, ProtoS0) ->
|
||||
{ProtoS1, ok} = write(ProtoS0, {KeyType, KeyData}),
|
||||
{ProtoS2, ok} = write(ProtoS1, {ValType, ValData}),
|
||||
ProtoS2
|
||||
end,
|
||||
Proto1,
|
||||
Data),
|
||||
{Proto3, ok} = write(Proto2, map_end),
|
||||
{Proto3, ok};
|
||||
|
||||
write(Proto, {{set, Type}, Data}) ->
|
||||
write(Proto0, {{set, Type}, Data}) ->
|
||||
true = sets:is_set(Data),
|
||||
ok = write(Proto,
|
||||
#protocol_set_begin{
|
||||
etype = term_to_typeid(Type),
|
||||
size = sets:size(Data)
|
||||
}),
|
||||
sets:fold(fun(Elem, _Acc) ->
|
||||
ok = write(Proto, {Type, Elem})
|
||||
end,
|
||||
_Acc0 = ok,
|
||||
Data),
|
||||
ok = write(Proto, set_end),
|
||||
ok;
|
||||
{Proto1, ok} = write(Proto0,
|
||||
#protocol_set_begin{
|
||||
etype = term_to_typeid(Type),
|
||||
size = sets:size(Data)
|
||||
}),
|
||||
Proto2 = sets:fold(fun(Elem, ProtoIn) ->
|
||||
{ProtoOut, ok} = write(ProtoIn, {Type, Elem}),
|
||||
ProtoOut
|
||||
end,
|
||||
Proto1,
|
||||
Data),
|
||||
{Proto3, ok} = write(Proto2, set_end),
|
||||
{Proto3, ok};
|
||||
|
||||
write(#protocol{module = Module,
|
||||
data = ModuleData}, Data) ->
|
||||
Module:write(ModuleData, Data).
|
||||
write(Proto = #protocol{module = Module,
|
||||
data = ModuleData}, Data) ->
|
||||
{NewData, Result} = Module:write(ModuleData, Data),
|
||||
{Proto#protocol{data = NewData}, Result}.
|
||||
|
||||
struct_write_loop(Proto, [{Fid, Type} | RestStructDef], [Data | RestData]) ->
|
||||
case Data of
|
||||
undefined ->
|
||||
% null fields are skipped in response
|
||||
skip;
|
||||
_ ->
|
||||
ok = write(Proto,
|
||||
#protocol_field_begin{
|
||||
type = term_to_typeid(Type),
|
||||
id = Fid
|
||||
}),
|
||||
ok = write(Proto, {Type, Data}),
|
||||
ok = write(Proto, field_end)
|
||||
end,
|
||||
struct_write_loop(Proto, RestStructDef, RestData);
|
||||
struct_write_loop(Proto0, [{Fid, Type} | RestStructDef], [Data | RestData]) ->
|
||||
NewProto = case Data of
|
||||
undefined ->
|
||||
Proto0; % null fields are skipped in response
|
||||
_ ->
|
||||
{Proto1, ok} = write(Proto0,
|
||||
#protocol_field_begin{
|
||||
type = term_to_typeid(Type),
|
||||
id = Fid
|
||||
}),
|
||||
{Proto2, ok} = write(Proto1, {Type, Data}),
|
||||
{Proto3, ok} = write(Proto2, field_end),
|
||||
Proto3
|
||||
end,
|
||||
struct_write_loop(NewProto, RestStructDef, RestData);
|
||||
struct_write_loop(Proto, [], []) ->
|
||||
ok = write(Proto, field_stop),
|
||||
ok.
|
||||
write(Proto, field_stop).
|
||||
|
Loading…
Reference in New Issue
Block a user