Coverage Report

Created: 2025-09-08 07:07

/src/grpc-swift/Sources/GRPC/WriteCapturingHandler.swift
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2020, gRPC Authors All rights reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
import NIOCore
17
18
/// A handler which redirects all writes into a callback until the `.end` part is seen, after which
19
/// all writes will be failed.
20
///
21
/// This handler is intended for use with 'fake' response streams the 'FakeChannel'.
22
internal final class WriteCapturingHandler<Request>: ChannelOutboundHandler {
23
  typealias OutboundIn = _GRPCClientRequestPart<Request>
24
  typealias RequestHandler = (FakeRequestPart<Request>) -> Void
25
26
  private var state: State
27
  private enum State {
28
    case active(RequestHandler)
29
    case inactive
30
  }
31
32
0
  internal init(requestHandler: @escaping RequestHandler) {
33
0
    self.state = .active(requestHandler)
34
0
  }
35
36
  internal func write(
37
    context: ChannelHandlerContext,
38
    data: NIOAny,
39
    promise: EventLoopPromise<Void>?
40
0
  ) {
41
0
    guard case let .active(handler) = self.state else {
42
0
      promise?.fail(ChannelError.ioOnClosedChannel)
43
0
      return
44
0
    }
45
0
46
0
    switch self.unwrapOutboundIn(data) {
47
0
    case let .head(requestHead):
48
0
      handler(.metadata(requestHead.customMetadata))
49
0
50
0
    case let .message(messageContext):
51
0
      handler(.message(messageContext.message))
52
0
53
0
    case .end:
54
0
      handler(.end)
55
0
      // We're done now.
56
0
      self.state = .inactive
57
0
    }
58
0
59
0
    promise?.succeed(())
60
0
  }
61
}