]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | %% |
2 | %% Licensed to the Apache Software Foundation (ASF) under one | |
3 | %% or more contributor license agreements. See the NOTICE file | |
4 | %% distributed with this work for additional information | |
5 | %% regarding copyright ownership. The ASF licenses this file | |
6 | %% to you under the Apache License, Version 2.0 (the | |
7 | %% "License"); you may not use this file except in compliance | |
8 | %% with the License. You may obtain a copy of the License at | |
9 | %% | |
10 | %% http://www.apache.org/licenses/LICENSE-2.0 | |
11 | %% | |
12 | %% Unless required by applicable law or agreed to in writing, | |
13 | %% software distributed under the License is distributed on an | |
14 | %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | %% KIND, either express or implied. See the License for the | |
16 | %% specific language governing permissions and limitations | |
17 | %% under the License. | |
18 | %% | |
19 | ||
20 | -module(thrift_transport). | |
21 | ||
22 | -export([behaviour_info/1]). | |
23 | %% constructors | |
24 | -export([new/1, new/2]). | |
25 | %% transport callbacks | |
26 | -export([read/2, read_exact/2, write/2, flush/1, close/1]). | |
27 | ||
28 | -export_type([t_transport/0]). | |
29 | ||
30 | ||
31 | behaviour_info(callbacks) -> | |
32 | [{read, 2}, {write, 2}, {flush, 1}, {close, 1}]. | |
33 | ||
34 | ||
35 | -record(t_transport, { | |
36 | module, | |
37 | state | |
38 | }). | |
39 | ||
40 | -type state() :: #t_transport{}. | |
41 | -type t_transport() :: #t_transport{}. | |
42 | ||
43 | ||
44 | -ifdef(transport_wrapper_module). | |
45 | -define(debug_wrap(Transport), | |
46 | case Transport#t_transport.module of | |
47 | ?transport_wrapper_module -> Transport; | |
48 | _Else -> | |
49 | {ok, Result} = ?transport_wrapper_module:new(Transport), | |
50 | Result | |
51 | end | |
52 | ). | |
53 | -else. | |
54 | -define(debug_wrap(Transport), Transport). | |
55 | -endif. | |
56 | ||
57 | ||
58 | -type wrappable() :: | |
59 | binary() | | |
60 | list() | | |
61 | {membuffer, binary() | list()} | | |
62 | {tcp, port()} | | |
63 | {tcp, port(), list()} | | |
64 | {file, file:io_device()} | | |
65 | {file, file:io_device(), list()} | | |
66 | {file, file:filename()} | | |
67 | {file, file:filename(), list()}. | |
68 | ||
69 | -spec new(wrappable()) -> {ok, #t_transport{}}. | |
70 | ||
71 | new({membuffer, Membuffer}) when is_binary(Membuffer); is_list(Membuffer) -> | |
72 | thrift_membuffer_transport:new(Membuffer); | |
73 | new({membuffer, Membuffer, []}) when is_binary(Membuffer); is_list(Membuffer) -> | |
74 | thrift_membuffer_transport:new(Membuffer); | |
75 | new({tcp, Socket}) when is_port(Socket) -> | |
76 | new({tcp, Socket, []}); | |
77 | new({tcp, Socket, Opts}) when is_port(Socket) -> | |
78 | thrift_socket_transport:new(Socket, Opts); | |
79 | new({file, Filename}) when is_list(Filename); is_binary(Filename) -> | |
80 | new({file, Filename, []}); | |
81 | new({file, Filename, Opts}) when is_list(Filename); is_binary(Filename) -> | |
82 | {ok, File} = file:open(Filename, [raw, binary]), | |
83 | new({file, File, Opts}); | |
84 | new({file, File, Opts}) -> | |
85 | thrift_file_transport:new(File, Opts). | |
86 | ||
87 | -spec new(Module::module(), State::any()) -> {ok, #t_transport{}}. | |
88 | ||
89 | new(Module, State) when is_atom(Module) -> | |
90 | {ok, ?debug_wrap(#t_transport{module = Module, state = State})}. | |
91 | ||
92 | ||
93 | -include("thrift_transport_behaviour.hrl"). | |
94 | ||
95 | ||
96 | read(Transport = #t_transport{module = Module}, Len) | |
97 | when is_integer(Len), Len >= 0 -> | |
98 | {NewState, Result} = Module:read(Transport#t_transport.state, Len), | |
99 | {Transport#t_transport{state = NewState}, Result}. | |
100 | ||
101 | ||
102 | read_exact(Transport = #t_transport{module = Module}, Len) | |
103 | when is_integer(Len), Len >= 0 -> | |
104 | case lists:keyfind(read_exact, 1, Module:module_info(exports)) of | |
105 | {read_exact, 2} -> | |
106 | {NewState, Result} = Module:read_exact(Transport#t_transport.state, Len), | |
107 | {Transport#t_transport{state = NewState}, Result}; | |
108 | _ -> | |
109 | read(Transport, Len) | |
110 | end. | |
111 | ||
112 | ||
113 | write(Transport = #t_transport{module = Module}, Data) -> | |
114 | {NewState, Result} = Module:write(Transport#t_transport.state, Data), | |
115 | {Transport#t_transport{state = NewState}, Result}. | |
116 | ||
117 | ||
118 | flush(Transport = #t_transport{module = Module}) -> | |
119 | {NewState, Result} = Module:flush(Transport#t_transport.state), | |
120 | {Transport#t_transport{state = NewState}, Result}. | |
121 | ||
122 | ||
123 | close(Transport = #t_transport{module = Module}) -> | |
124 | {NewState, Result} = Module:close(Transport#t_transport.state), | |
125 | {Transport#t_transport{state = NewState}, Result}. | |
126 |