/src/grpc-swift/Sources/GRPC/InterceptorContextList.swift
Line | Count | Source |
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 | | |
17 | | /// A non-empty list which is guaranteed to have a first and last element. |
18 | | /// |
19 | | /// This is required since we want to directly store the first and last elements: in some cases |
20 | | /// `Array.first` and `Array.last` will allocate: unfortunately this currently happens to be the |
21 | | /// case for the interceptor pipelines. Storing the `first` and `last` directly allows us to avoid |
22 | | /// this. See also: https://bugs.swift.org/browse/SR-11262. |
23 | | @usableFromInline |
24 | | internal struct InterceptorContextList<Element> { |
25 | | /// The first element, stored at `middle.startIndex - 1`. |
26 | | @usableFromInline |
27 | | internal var first: Element |
28 | | |
29 | | /// The last element, stored at the `middle.endIndex`. |
30 | | @usableFromInline |
31 | | internal var last: Element |
32 | | |
33 | | /// The other elements. |
34 | | @usableFromInline |
35 | | internal var _middle: [Element] |
36 | | |
37 | | /// The index of `first` |
38 | | @usableFromInline |
39 | | internal let firstIndex: Int |
40 | | |
41 | | /// The index of `last`. |
42 | | @usableFromInline |
43 | | internal let lastIndex: Int |
44 | | |
45 | | @usableFromInline |
46 | 0 | internal subscript(checked index: Int) -> Element? { |
47 | 0 | switch index { |
48 | 0 | case self.firstIndex: |
49 | 0 | return self.first |
50 | 0 | case self.lastIndex: |
51 | 0 | return self.last |
52 | 0 | default: |
53 | 0 | return self._middle[checked: index] |
54 | 0 | } |
55 | 0 | } |
56 | | |
57 | | @inlinable |
58 | 0 | internal init(first: Element, middle: [Element], last: Element) { |
59 | 0 | self.first = first |
60 | 0 | self._middle = middle |
61 | 0 | self.last = last |
62 | 0 | self.firstIndex = middle.startIndex - 1 |
63 | 0 | self.lastIndex = middle.endIndex |
64 | 0 | } |
65 | | } |