THRIFT-5635 Update erlang client for Erlang 23-25
Client: erl
Patch: Sergey Yelin
This closes #2677
Summary of changes:
- Add useful compiler options
- Format sources using erlfmt
- Switch to modern callbacks in thrift_* modules
- Add static analysis (dialyzer), disabled by default
- Add/fix types for API calls
NOTE: Enabling static analysis requires additional tweaks in multiplexer module.
diff --git a/lib/erl/src/thrift_transport.erl b/lib/erl/src/thrift_transport.erl
index 2414bde..cc9ca1b 100644
--- a/lib/erl/src/thrift_transport.erl
+++ b/lib/erl/src/thrift_transport.erl
@@ -19,108 +19,105 @@
-module(thrift_transport).
--export([behaviour_info/1]).
%% constructors
-export([new/1, new/2]).
%% transport callbacks
-export([read/2, read_exact/2, write/2, flush/1, close/1]).
+-record(t_transport, {
+ module :: module(),
+ state :: term()
+}).
+-type t_transport() :: #t_transport{}.
-export_type([t_transport/0]).
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+-type state() :: term().
+-export_type([state/0]).
+-type reason() :: term().
+-export_type([reason/0]).
-behaviour_info(callbacks) ->
- [{read, 2}, {write, 2}, {flush, 1}, {close, 1}].
-
-
--record(t_transport, {
- module,
- state
-}).
-
--type state() :: #t_transport{}.
--type t_transport() :: #t_transport{}.
-
+-callback write(state(), iolist() | binary()) -> {state(), ok | {error, reason()}}.
+-callback read(state(), non_neg_integer()) -> {state(), {ok, binary()} | {error, reason()}}.
+-callback flush(state()) -> {state(), ok | {error, reason()}}.
+-callback close(state()) -> {state(), ok | {error, reason()}}.
-ifdef(transport_wrapper_module).
-define(debug_wrap(Transport),
- case Transport#t_transport.module of
- ?transport_wrapper_module -> Transport;
- _Else ->
- {ok, Result} = ?transport_wrapper_module:new(Transport),
- Result
- end
+ case Transport#t_transport.module of
+ ?transport_wrapper_module ->
+ Transport;
+ _Else ->
+ {ok, Result} = ?transport_wrapper_module:new(Transport),
+ Result
+ end
).
-else.
-define(debug_wrap(Transport), Transport).
-endif.
-
-type wrappable() ::
- binary() |
- list() |
- {membuffer, binary() | list()} |
- {tcp, port()} |
- {tcp, port(), list()} |
- {file, file:io_device()} |
- {file, file:io_device(), list()} |
- {file, file:filename()} |
- {file, file:filename(), list()}.
+ binary()
+ | list()
+ | {membuffer, binary() | list()}
+ | {membuffer, binary() | list(), list()}
+ | {tcp, port()}
+ | {tcp, port(), list()}
+ | {file, file:io_device()}
+ | {file, file:io_device(), list()}
+ | {file, file:filename()}
+ | {file, file:filename(), list()}.
-spec new(wrappable()) -> {ok, #t_transport{}}.
-new({membuffer, Membuffer}) when is_binary(Membuffer); is_list(Membuffer) ->
- thrift_membuffer_transport:new(Membuffer);
-new({membuffer, Membuffer, []}) when is_binary(Membuffer); is_list(Membuffer) ->
- thrift_membuffer_transport:new(Membuffer);
+new({membuffer, Membuffer}) ->
+ new({membuffer, Membuffer, []});
+new({membuffer, Membuffer, Opts}) when is_binary(Membuffer); is_list(Membuffer) ->
+ thrift_membuffer_transport:new(Membuffer, Opts);
new({tcp, Socket}) when is_port(Socket) ->
- new({tcp, Socket, []});
+ new({tcp, Socket, []});
new({tcp, Socket, Opts}) when is_port(Socket) ->
- thrift_socket_transport:new(Socket, Opts);
+ thrift_socket_transport:new(Socket, Opts);
new({file, Filename}) when is_list(Filename); is_binary(Filename) ->
- new({file, Filename, []});
+ new({file, Filename, []});
new({file, Filename, Opts}) when is_list(Filename); is_binary(Filename) ->
- {ok, File} = file:open(Filename, [raw, binary]),
- new({file, File, Opts});
+ {ok, File} = file:open(Filename, [raw, binary]),
+ new({file, File, Opts});
new({file, File, Opts}) ->
- thrift_file_transport:new(File, Opts).
+ thrift_file_transport:new(File, Opts).
--spec new(Module::module(), State::any()) -> {ok, #t_transport{}}.
+-spec new(Module :: module(), State :: any()) -> {ok, t_transport()}.
new(Module, State) when is_atom(Module) ->
- {ok, ?debug_wrap(#t_transport{module = Module, state = State})}.
+ {ok, ?debug_wrap(#t_transport{module = Module, state = State})}.
+read(Transport = #t_transport{module = Module}, Len) when
+ is_integer(Len), Len >= 0
+->
+ {NewState, Result} = Module:read(Transport#t_transport.state, Len),
+ {Transport#t_transport{state = NewState}, Result}.
--include("thrift_transport_behaviour.hrl").
-
-
-read(Transport = #t_transport{module = Module}, Len)
-when is_integer(Len), Len >= 0 ->
- {NewState, Result} = Module:read(Transport#t_transport.state, Len),
- {Transport#t_transport{state = NewState}, Result}.
-
-
-read_exact(Transport = #t_transport{module = Module}, Len)
-when is_integer(Len), Len >= 0 ->
- case lists:keyfind(read_exact, 1, Module:module_info(exports)) of
- {read_exact, 2} ->
- {NewState, Result} = Module:read_exact(Transport#t_transport.state, Len),
- {Transport#t_transport{state = NewState}, Result};
- _ ->
- read(Transport, Len)
- end.
-
+read_exact(Transport = #t_transport{module = Module}, Len) when
+ is_integer(Len), Len >= 0
+->
+ case lists:keyfind(read_exact, 1, Module:module_info(exports)) of
+ {read_exact, 2} ->
+ {NewState, Result} = Module:read_exact(Transport#t_transport.state, Len),
+ {Transport#t_transport{state = NewState}, Result};
+ _ ->
+ read(Transport, Len)
+ end.
write(Transport = #t_transport{module = Module}, Data) ->
- {NewState, Result} = Module:write(Transport#t_transport.state, Data),
- {Transport#t_transport{state = NewState}, Result}.
-
+ {NewState, Result} = Module:write(Transport#t_transport.state, Data),
+ {Transport#t_transport{state = NewState}, Result}.
flush(Transport = #t_transport{module = Module}) ->
- {NewState, Result} = Module:flush(Transport#t_transport.state),
- {Transport#t_transport{state = NewState}, Result}.
-
+ {NewState, Result} = Module:flush(Transport#t_transport.state),
+ {Transport#t_transport{state = NewState}, Result}.
close(Transport = #t_transport{module = Module}) ->
- {NewState, Result} = Module:close(Transport#t_transport.state),
- {Transport#t_transport{state = NewState}, Result}.
-
+ {NewState, Result} = Module:close(Transport#t_transport.state),
+ {Transport#t_transport{state = NewState}, Result}.