grpc_kit 0.1.14 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +4 -0
- data/examples/interceptors/call_stream.rb +18 -0
- data/examples/interceptors/client_logging_interceptor.rb +6 -17
- data/examples/interceptors/server_logging_interceptor.rb +6 -9
- data/examples/routeguide_client.rb +7 -10
- data/examples/routeguide_server.rb +4 -6
- data/lib/grpc_kit.rb +1 -1
- data/lib/grpc_kit/call.rb +45 -0
- data/lib/grpc_kit/calls.rb +2 -52
- data/lib/grpc_kit/calls/client_bidi_streamer.rb +13 -11
- data/lib/grpc_kit/calls/client_client_streamer.rb +5 -15
- data/lib/grpc_kit/calls/client_request_response.rb +6 -11
- data/lib/grpc_kit/calls/client_server_streamer.rb +7 -14
- data/lib/grpc_kit/calls/server_bidi_streamer.rb +11 -10
- data/lib/grpc_kit/calls/server_client_streamer.rb +12 -10
- data/lib/grpc_kit/calls/server_request_response.rb +6 -10
- data/lib/grpc_kit/calls/server_server_streamer.rb +5 -11
- data/lib/grpc_kit/errors.rb +17 -17
- data/lib/grpc_kit/grpc/dsl.rb +1 -1
- data/lib/grpc_kit/grpc/interceptor.rb +8 -8
- data/lib/grpc_kit/interceptor_registory.rb +35 -0
- data/lib/grpc_kit/interceptors.rb +6 -12
- data/lib/grpc_kit/interceptors/client_request_response.rb +6 -9
- data/lib/grpc_kit/interceptors/server_request_response.rb +7 -10
- data/lib/grpc_kit/rpcs/client_bidi_streamer.rb +1 -1
- data/lib/grpc_kit/rpcs/client_client_streamer.rb +1 -1
- data/lib/grpc_kit/rpcs/client_request_response.rb +6 -6
- data/lib/grpc_kit/rpcs/client_server_streamer.rb +9 -4
- data/lib/grpc_kit/rpcs/server_bidi_streamer.rb +5 -1
- data/lib/grpc_kit/rpcs/server_client_streamer.rb +7 -3
- data/lib/grpc_kit/rpcs/server_request_response.rb +15 -11
- data/lib/grpc_kit/rpcs/server_server_streamer.rb +7 -3
- data/lib/grpc_kit/session/server_session.rb +1 -1
- data/lib/grpc_kit/status_codes.rb +17 -17
- data/lib/grpc_kit/stream/client_stream.rb +3 -10
- data/lib/grpc_kit/stream/server_stream.rb +0 -5
- data/lib/grpc_kit/version.rb +1 -1
- metadata +5 -2
@@ -1,36 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/call'
|
3
4
|
require 'grpc_kit/calls'
|
4
5
|
|
5
6
|
module GrpcKit
|
6
7
|
module Calls::Client
|
7
|
-
class ServerStreamer < GrpcKit::
|
8
|
+
class ServerStreamer < GrpcKit::Call
|
8
9
|
include Enumerable
|
9
10
|
|
10
11
|
alias outgoing_metadata metadata
|
11
12
|
|
12
13
|
# @param data [Object] request message
|
13
|
-
# @param last [Boolean]
|
14
14
|
# @return [void]
|
15
|
-
def send_msg(data
|
16
|
-
|
17
|
-
|
18
|
-
@stream.send_msg(data, last: last, metadata: outgoing_metadata)
|
15
|
+
def send_msg(data)
|
16
|
+
@stream.send_msg(data, last: true, metadata: outgoing_metadata)
|
19
17
|
end
|
20
18
|
|
21
|
-
# @param last [Boolean]
|
22
19
|
# @return [Object] response object
|
23
|
-
def recv
|
24
|
-
|
25
|
-
|
26
|
-
@stream.recv_msg(last: last)
|
20
|
+
def recv
|
21
|
+
@stream.recv_msg
|
27
22
|
end
|
28
23
|
|
29
24
|
# @yieldparam response [Object] each response object of server streaming RPC
|
30
25
|
def each
|
31
|
-
loop
|
32
|
-
yield(recv)
|
33
|
-
end
|
26
|
+
loop { yield(recv) }
|
34
27
|
end
|
35
28
|
end
|
36
29
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/call'
|
3
4
|
require 'grpc_kit/calls'
|
4
5
|
|
5
6
|
module GrpcKit
|
6
7
|
module Calls::Server
|
7
|
-
class BidiStreamer < GrpcKit::
|
8
|
+
class BidiStreamer < GrpcKit::Call
|
9
|
+
include Enumerable
|
10
|
+
|
8
11
|
attr_reader :outgoing_initial_metadata, :outgoing_trailing_metadata
|
9
12
|
alias incoming_metadata metadata
|
10
13
|
|
@@ -16,27 +19,25 @@ module GrpcKit
|
|
16
19
|
end
|
17
20
|
|
18
21
|
# @param data [Object] request message
|
19
|
-
# @param last [Boolean]
|
20
22
|
# @return [void]
|
21
|
-
def send_msg(data
|
22
|
-
raise 'No method error' if @restrict
|
23
|
-
|
23
|
+
def send_msg(data)
|
24
24
|
@stream.send_msg(
|
25
25
|
data,
|
26
26
|
@protobuf,
|
27
|
-
last: last,
|
28
27
|
initial_metadata: @outgoing_initial_metadata,
|
29
28
|
trailing_metadata: @outgoing_trailing_metadata,
|
30
29
|
limit_size: @config.max_send_message_size,
|
31
30
|
)
|
32
31
|
end
|
33
32
|
|
34
|
-
# @param last [Boolean]
|
35
33
|
# @return [Object] response object
|
36
|
-
def recv
|
37
|
-
|
34
|
+
def recv
|
35
|
+
@stream.recv_msg(@protobuf, limit_size: @config.max_receive_message_size)
|
36
|
+
end
|
38
37
|
|
39
|
-
|
38
|
+
# @yieldparam response [Object] each response object of bidi streaming RPC
|
39
|
+
def each
|
40
|
+
loop { yield(recv) }
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/call'
|
3
4
|
require 'grpc_kit/calls'
|
4
5
|
|
5
6
|
module GrpcKit
|
6
7
|
module Calls::Server
|
7
|
-
class ClientStreamer < GrpcKit::
|
8
|
+
class ClientStreamer < GrpcKit::Call
|
9
|
+
include Enumerable
|
10
|
+
|
8
11
|
attr_reader :outgoing_initial_metadata, :outgoing_trailing_metadata
|
9
12
|
alias incoming_metadata metadata
|
10
13
|
|
@@ -16,27 +19,26 @@ module GrpcKit
|
|
16
19
|
end
|
17
20
|
|
18
21
|
# @param data [Object] request message
|
19
|
-
# @param last [Boolean]
|
20
22
|
# @return [void]
|
21
|
-
def send_msg(data
|
22
|
-
raise 'No method error' if @restrict
|
23
|
-
|
23
|
+
def send_msg(data)
|
24
24
|
@stream.send_msg(
|
25
25
|
data,
|
26
26
|
@protobuf,
|
27
|
-
last:
|
27
|
+
last: true,
|
28
28
|
initial_metadata: @outgoing_initial_metadata,
|
29
29
|
trailing_metadata: @outgoing_trailing_metadata,
|
30
30
|
limit_size: @config.max_send_message_size,
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
34
|
-
# @param last [Boolean]
|
35
34
|
# @return [Object] response object
|
36
|
-
def recv
|
37
|
-
|
35
|
+
def recv
|
36
|
+
@stream.recv_msg(@protobuf, limit_size: @config.max_receive_message_size)
|
37
|
+
end
|
38
38
|
|
39
|
-
|
39
|
+
# @yieldparam response [Object] each response object of client streaming RPC
|
40
|
+
def each
|
41
|
+
loop { yield(recv) }
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/call'
|
3
4
|
require 'grpc_kit/calls'
|
4
5
|
|
5
6
|
module GrpcKit
|
6
7
|
module Calls::Server
|
7
|
-
class RequestResponse < GrpcKit::
|
8
|
+
class RequestResponse < GrpcKit::Call
|
8
9
|
attr_reader :outgoing_initial_metadata, :outgoing_trailing_metadata
|
9
10
|
alias incoming_metadata metadata
|
10
11
|
|
@@ -18,25 +19,20 @@ module GrpcKit
|
|
18
19
|
# @param data [Object] request message
|
19
20
|
# @param last [Boolean]
|
20
21
|
# @return [void]
|
21
|
-
def send_msg(data
|
22
|
-
raise 'No method error' if @restrict
|
23
|
-
|
22
|
+
def send_msg(data)
|
24
23
|
@stream.send_msg(
|
25
24
|
data,
|
26
25
|
@protobuf,
|
27
|
-
last:
|
26
|
+
last: true,
|
28
27
|
initial_metadata: @outgoing_initial_metadata,
|
29
28
|
trailing_metadata: @outgoing_trailing_metadata,
|
30
29
|
limit_size: @config.max_send_message_size,
|
31
30
|
)
|
32
31
|
end
|
33
32
|
|
34
|
-
# @param last [Boolean]
|
35
33
|
# @return [Object] response object
|
36
|
-
def recv
|
37
|
-
|
38
|
-
|
39
|
-
@stream.recv_msg(@protobuf, last: last, limit_size: @config.max_receive_message_size)
|
34
|
+
def recv
|
35
|
+
@stream.recv_msg(@protobuf, last: true, limit_size: @config.max_receive_message_size)
|
40
36
|
end
|
41
37
|
end
|
42
38
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/call'
|
3
4
|
require 'grpc_kit/calls'
|
4
5
|
|
5
6
|
module GrpcKit
|
6
7
|
module Calls::Server
|
7
|
-
class ServerStreamer < GrpcKit::
|
8
|
+
class ServerStreamer < GrpcKit::Call
|
8
9
|
attr_reader :outgoing_initial_metadata, :outgoing_trailing_metadata
|
9
10
|
alias incoming_metadata metadata
|
10
11
|
|
@@ -16,27 +17,20 @@ module GrpcKit
|
|
16
17
|
end
|
17
18
|
|
18
19
|
# @param data [Object] request message
|
19
|
-
# @param last [Boolean]
|
20
20
|
# @return [void]
|
21
|
-
def send_msg(data
|
22
|
-
raise 'No method error' if @restrict
|
23
|
-
|
21
|
+
def send_msg(data)
|
24
22
|
@stream.send_msg(
|
25
23
|
data,
|
26
24
|
@protobuf,
|
27
|
-
last: last,
|
28
25
|
initial_metadata: @outgoing_initial_metadata,
|
29
26
|
trailing_metadata: @outgoing_trailing_metadata,
|
30
27
|
limit_size: @config.max_send_message_size,
|
31
28
|
)
|
32
29
|
end
|
33
30
|
|
34
|
-
# @param last [Boolean]
|
35
31
|
# @return [Object] response object
|
36
|
-
def recv
|
37
|
-
|
38
|
-
|
39
|
-
@stream.recv_msg(@protobuf, last: last, limit_size: @config.max_receive_message_size)
|
32
|
+
def recv
|
33
|
+
@stream.recv_msg(@protobuf, last: true, limit_size: @config.max_receive_message_size)
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
data/lib/grpc_kit/errors.rb
CHANGED
@@ -156,24 +156,24 @@ module GrpcKit
|
|
156
156
|
end
|
157
157
|
|
158
158
|
CODES = {
|
159
|
-
GrpcKit::StatusCodes::OK
|
160
|
-
GrpcKit::StatusCodes::CANCELLED
|
161
|
-
GrpcKit::StatusCodes::UNKNOWN
|
162
|
-
GrpcKit::StatusCodes::INVALID_ARGUMENT
|
163
|
-
GrpcKit::StatusCodes::DEADLINE_EXCEEDED
|
164
|
-
GrpcKit::StatusCodes::NOT_FOUND
|
165
|
-
GrpcKit::StatusCodes::ALREADY_EXISTS
|
166
|
-
GrpcKit::StatusCodes::PERMISSION_DENIED
|
167
|
-
GrpcKit::StatusCodes::RESOURCE_EXHAUSTED
|
159
|
+
GrpcKit::StatusCodes::OK => Ok,
|
160
|
+
GrpcKit::StatusCodes::CANCELLED => Cancelled,
|
161
|
+
GrpcKit::StatusCodes::UNKNOWN => Unknown,
|
162
|
+
GrpcKit::StatusCodes::INVALID_ARGUMENT => InvalidArgument,
|
163
|
+
GrpcKit::StatusCodes::DEADLINE_EXCEEDED => DeadlineExceeded,
|
164
|
+
GrpcKit::StatusCodes::NOT_FOUND => NotFound,
|
165
|
+
GrpcKit::StatusCodes::ALREADY_EXISTS => AlreadyExists,
|
166
|
+
GrpcKit::StatusCodes::PERMISSION_DENIED => PermissionDenied,
|
167
|
+
GrpcKit::StatusCodes::RESOURCE_EXHAUSTED => ResourceExhausted,
|
168
168
|
GrpcKit::StatusCodes::FAILED_PRECONDITION => FailedPrecondition,
|
169
|
-
GrpcKit::StatusCodes::ABORTED
|
170
|
-
GrpcKit::StatusCodes::OUT_OF_RANGE
|
171
|
-
GrpcKit::StatusCodes::UNIMPLEMENTED
|
172
|
-
GrpcKit::StatusCodes::INTERNAL
|
173
|
-
GrpcKit::StatusCodes::UNAVAILABLE
|
174
|
-
GrpcKit::StatusCodes::DATA_LOSS
|
175
|
-
GrpcKit::StatusCodes::UNAUTHENTICATED
|
176
|
-
GrpcKit::StatusCodes::DO_NOT_USE
|
169
|
+
GrpcKit::StatusCodes::ABORTED => Aborted,
|
170
|
+
GrpcKit::StatusCodes::OUT_OF_RANGE => OutOfRange,
|
171
|
+
GrpcKit::StatusCodes::UNIMPLEMENTED => Unimplemented,
|
172
|
+
GrpcKit::StatusCodes::INTERNAL => Internal,
|
173
|
+
GrpcKit::StatusCodes::UNAVAILABLE => Unavailable,
|
174
|
+
GrpcKit::StatusCodes::DATA_LOSS => DataLoss,
|
175
|
+
GrpcKit::StatusCodes::UNAUTHENTICATED => Unauthenticated,
|
176
|
+
GrpcKit::StatusCodes::DO_NOT_USE => DoNotUse,
|
177
177
|
}.freeze
|
178
178
|
end
|
179
179
|
end
|
data/lib/grpc_kit/grpc/dsl.rb
CHANGED
@@ -16,7 +16,7 @@ module GrpcKit
|
|
16
16
|
# @param request [Object,nil] An object which cliet will send
|
17
17
|
# @param call [GrpcKit::Calls::Client::RequestResponse,nil]
|
18
18
|
# @param metadata [Hash<String,String>,nil]
|
19
|
-
# @param method [GrpcKit::
|
19
|
+
# @param method [GrpcKit::Call::Name,nil]
|
20
20
|
def request_response(request: nil, call: nil, method: nil, metadata: nil)
|
21
21
|
yield
|
22
22
|
end
|
@@ -24,7 +24,7 @@ module GrpcKit
|
|
24
24
|
# @param requests [Object,nil] comptibility with grpc gem, no use
|
25
25
|
# @param call [GrpcKit::Calls::Client::ClientStreamer,nil]
|
26
26
|
# @param metadata [Hash<String,String>,nil]
|
27
|
-
# @param method [GrpcKit::
|
27
|
+
# @param method [GrpcKit::Call::Name,nil]
|
28
28
|
def client_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
29
29
|
yield
|
30
30
|
end
|
@@ -32,7 +32,7 @@ module GrpcKit
|
|
32
32
|
# @param request [Object,nil] An object which cliet will send
|
33
33
|
# @param call [GrpcKit::Calls::Client::ServerStreamer,nil]
|
34
34
|
# @param metadata [Hash<String,String>,nil]
|
35
|
-
# @param method [GrpcKit::
|
35
|
+
# @param method [GrpcKit::Call::Name,nil]
|
36
36
|
def server_streamer(request: nil, call: nil, method: nil, metadata: nil)
|
37
37
|
yield
|
38
38
|
end
|
@@ -40,7 +40,7 @@ module GrpcKit
|
|
40
40
|
# @param requests [Object,nil] comptibility with grpc gem, no use
|
41
41
|
# @param call [GrpcKit::Calls::Client::BidiStreamer,nil]
|
42
42
|
# @param metadata [Hash<String,String>,nil]
|
43
|
-
# @param method [GrpcKit::
|
43
|
+
# @param method [GrpcKit::Call::Name,nil]
|
44
44
|
def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
45
45
|
yield
|
46
46
|
end
|
@@ -53,27 +53,27 @@ module GrpcKit
|
|
53
53
|
|
54
54
|
# @param request [Object] An object which server received
|
55
55
|
# @param call [GrpcKit::Calls::Server::RequestResponse,nil]
|
56
|
-
# @param method [GrpcKit::
|
56
|
+
# @param method [GrpcKit::Call::Name,nil]
|
57
57
|
def request_response(request: nil, call: nil, method: nil)
|
58
58
|
yield
|
59
59
|
end
|
60
60
|
|
61
61
|
# @param call [GrpcKit::Calls::Server::ClientStreamer,nil]
|
62
|
-
# @param method [GrpcKit::
|
62
|
+
# @param method [GrpcKit::Call::Name,nil]
|
63
63
|
def client_streamer(call: nil, method: nil)
|
64
64
|
yield
|
65
65
|
end
|
66
66
|
|
67
67
|
# @param request [Object] An object which server received
|
68
68
|
# @param call [GrpcKit::Calls::Server::ServerStreamer,nil]
|
69
|
-
# @param method [GrpcKit::
|
69
|
+
# @param method [GrpcKit::Call::Name,nil]
|
70
70
|
def server_streamer(request: nil, call: nil, method: nil)
|
71
71
|
yield
|
72
72
|
end
|
73
73
|
|
74
74
|
# @param requests [Object,nil] comptibility with grpc gem, no use
|
75
75
|
# @param call [GrpcKit::Calls::Server::BidiStreamer,nil]
|
76
|
-
# @param method [GrpcKit::
|
76
|
+
# @param method [GrpcKit::Call::Name,nil]
|
77
77
|
def bidi_streamer(requests: nil, call: nil, method: nil)
|
78
78
|
yield
|
79
79
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GrpcKit
|
4
|
+
class InterceptorRegistry
|
5
|
+
def initialize(interceptors)
|
6
|
+
@interceptors = interceptors
|
7
|
+
|
8
|
+
validate_interceptors
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
@interceptors.dup
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validate_interceptors
|
18
|
+
unless @interceptors
|
19
|
+
raise ArgumentError, 'interceptors must not be nil'
|
20
|
+
end
|
21
|
+
|
22
|
+
if @interceptors.empty?
|
23
|
+
raise ArgumentError, 'interceptors must not be empty'
|
24
|
+
end
|
25
|
+
|
26
|
+
invalid_interceptors = @interceptors.reject do |interceptor|
|
27
|
+
interceptor.class.ancestors.include?(GrpcKit::GRPC::Interceptor)
|
28
|
+
end
|
29
|
+
|
30
|
+
unless invalid_interceptors.empty?
|
31
|
+
raise ArgumentError, "interceptor #{invalid_interceptors} must descend from #{GrpcKit::GRPC::Interceptor}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,21 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'grpc_kit/interceptor_registory'
|
4
|
+
|
3
5
|
module GrpcKit
|
4
6
|
module Interceptors
|
5
7
|
module Client
|
6
8
|
class Streaming
|
7
9
|
# @param interceptors [Array<GrpcKit::GRPC::ClientInterceptor>]
|
8
10
|
def initialize(interceptors)
|
9
|
-
@
|
11
|
+
@registry = GrpcKit::InterceptorRegistry.new(interceptors)
|
10
12
|
end
|
11
13
|
|
12
14
|
# @param metadata [Hash<String,String>]
|
13
15
|
def intercept(call, metadata, &block)
|
14
|
-
|
15
|
-
do_intercept(@interceptors.dup, call, metadata, &block)
|
16
|
-
else
|
17
|
-
yield(call, metadata)
|
18
|
-
end
|
16
|
+
do_intercept(@registry.build, call, metadata, &block)
|
19
17
|
end
|
20
18
|
|
21
19
|
private
|
@@ -39,15 +37,11 @@ module GrpcKit
|
|
39
37
|
class Streaming
|
40
38
|
# @param interceptors [Array<GrpcKit::GRPC::ServerInterceptor>]
|
41
39
|
def initialize(interceptors)
|
42
|
-
@
|
40
|
+
@registry = GrpcKit::InterceptorRegistry.new(interceptors)
|
43
41
|
end
|
44
42
|
|
45
43
|
def intercept(call, &block)
|
46
|
-
|
47
|
-
do_intercept(@interceptors.dup, call, &block)
|
48
|
-
else
|
49
|
-
yield(call)
|
50
|
-
end
|
44
|
+
do_intercept(@registry.build, call, &block)
|
51
45
|
end
|
52
46
|
|
53
47
|
private
|
@@ -7,30 +7,27 @@ module GrpcKit
|
|
7
7
|
class RequestResponse
|
8
8
|
# @param interceptors [Array<GrpcKit::GRPC::ClientInterceptor>]
|
9
9
|
def initialize(interceptors)
|
10
|
-
@
|
10
|
+
@registry = GrpcKit::InterceptorRegistry.new(interceptors)
|
11
11
|
end
|
12
12
|
|
13
13
|
# @param call [GrpcKit::Calls::Client::RequestResponse]
|
14
14
|
# @param metadata [Hash<String,String>]
|
15
|
+
# @yieldreturn [Object] Response object server sent
|
15
16
|
def intercept(request, call, metadata, &block)
|
16
|
-
|
17
|
-
do_intercept(@interceptors.dup, request, call, metadata, &block)
|
18
|
-
else
|
19
|
-
yield(request, call, metadata)
|
20
|
-
end
|
17
|
+
do_intercept(@registry.build, request, call, metadata, &block)
|
21
18
|
end
|
22
19
|
|
23
20
|
private
|
24
21
|
|
25
22
|
def do_intercept(interceptors, request, call, metadata)
|
26
23
|
if interceptors.empty?
|
27
|
-
return yield
|
24
|
+
return yield
|
28
25
|
end
|
29
26
|
|
30
27
|
interceptor = interceptors.pop
|
31
28
|
interceptor.request_response(request: request, call: call, method: call.method, metadata: metadata) do
|
32
|
-
do_intercept(interceptors, request, call, metadata) do
|
33
|
-
yield
|
29
|
+
do_intercept(interceptors, request, call, metadata) do
|
30
|
+
yield
|
34
31
|
end
|
35
32
|
end
|
36
33
|
end
|