blob: 9d89d14a92ea9f71f720e8430fcab3a3301a79a9 [file] [log] [blame]
Chris Simpsona9b6c702018-04-08 07:11:37 -04001/*
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
20import Foundation
21
22public struct TSet<Element : TSerializable & Hashable> : SetAlgebra, Hashable, Collection, ExpressibleByArrayLiteral, TSerializable {
23 /// Typealias for Storage type
Chris Simpson2566ecd2018-08-29 14:40:44 -040024 public typealias Storage = Set<Element>
Chris Simpsona9b6c702018-04-08 07:11:37 -040025
26
27 /// Internal Storage used for TSet (Set\<Element\>)
28 internal var storage : Storage
29
30
31 /// Mark: Collection
32
Jano Svitok3127e4a2020-04-27 09:12:42 +020033 public typealias Element = Storage.Element
Chris Simpsona9b6c702018-04-08 07:11:37 -040034 public typealias Indices = Storage.Indices
35 public typealias Index = Storage.Index
Antoine Cœur08a6eb62019-07-08 18:42:09 +080036 public typealias IndexDistance = Int
Chris Simpsona9b6c702018-04-08 07:11:37 -040037 public typealias SubSequence = Storage.SubSequence
38
39
40 public var indices: Indices { return storage.indices }
41
42 // Must implement isEmpty even though both SetAlgebra and Collection provide it due to their conflciting default implementations
43 public var isEmpty: Bool { return storage.isEmpty }
44
45 public func distance(from start: Index, to end: Index) -> IndexDistance {
46 return storage.distance(from: start, to: end)
47 }
48
49 public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
50 return storage.index(i, offsetBy: n)
51 }
52
53 public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
54 return storage.index(i, offsetBy: n, limitedBy: limit)
55 }
56
57 #if swift(>=3.2)
58 public subscript (position: Storage.Index) -> Element {
59 return storage[position]
60 }
61 #else
62 public subscript (position: Storage.Index) -> Element? {
63 return storage[position]
64 }
65 #endif
66
67 /// Mark: SetAlgebra
68 internal init(storage: Set<Element>) {
69 self.storage = storage
70 }
71
72 public func contains(_ member: Element) -> Bool {
73 return storage.contains(member)
74 }
75
76 public mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) {
77 return storage.insert(newMember)
78 }
79
80 public mutating func remove(_ member: Element) -> Element? {
81 return storage.remove(member)
82 }
83
84 public func union(_ other: TSet<Element>) -> TSet {
85 return TSet(storage: storage.union(other.storage))
86 }
87
88 public mutating func formIntersection(_ other: TSet<Element>) {
89 return storage.formIntersection(other.storage)
90 }
91
92 public mutating func formSymmetricDifference(_ other: TSet<Element>) {
93 return storage.formSymmetricDifference(other.storage)
94 }
95
96 public mutating func formUnion(_ other: TSet<Element>) {
97 return storage.formUnion(other.storage)
98 }
99
100 public func intersection(_ other: TSet<Element>) -> TSet {
101 return TSet(storage: storage.intersection(other.storage))
102 }
103
104 public func symmetricDifference(_ other: TSet<Element>) -> TSet {
105 return TSet(storage: storage.symmetricDifference(other.storage))
106 }
107
108 public mutating func update(with newMember: Element) -> Element? {
109 return storage.update(with: newMember)
110 }
111
112 /// Mark: IndexableBase
113
114 public var startIndex: Index { return storage.startIndex }
115 public var endIndex: Index { return storage.endIndex }
116 public func index(after i: Index) -> Index {
117 return storage.index(after: i)
118 }
119
120 public func formIndex(after i: inout Storage.Index) {
121 storage.formIndex(after: &i)
122 }
123
124 public subscript(bounds: Range<Index>) -> SubSequence {
125 return storage[bounds]
126 }
127
128
129 /// Mark: Hashable
Alexander Edgeb4711a62020-04-24 14:43:03 +0100130 public func hash(into hasher: inout Hasher) {
131 hasher.combine(storage)
Chris Simpsona9b6c702018-04-08 07:11:37 -0400132 }
133
134 /// Mark: TSerializable
135 public static var thriftType : TType { return .set }
136
137 public init() {
138 storage = Storage()
139 }
140
141 public init(arrayLiteral elements: Element...) {
142 self.storage = Storage(elements)
143 }
144
145 public init<Source : Sequence>(_ sequence: Source) where Source.Iterator.Element == Element {
146 storage = Storage(sequence)
147 }
148
149 public static func read(from proto: TProtocol) throws -> TSet {
150 let (elementType, size) = try proto.readSetBegin()
151 if elementType != Element.thriftType {
152 throw TProtocolError(error: .invalidData,
153 extendedError: .unexpectedType(type: elementType))
154 }
155 var set = TSet()
156 for _ in 0..<size {
157 let element = try Element.read(from: proto)
158 set.storage.insert(element)
159 }
160 try proto.readSetEnd()
161 return set
162 }
163
164 public func write(to proto: TProtocol) throws {
165 try proto.writeSetBegin(elementType: Element.thriftType, size: Int32(self.count))
166 for element in self.storage {
167 try Element.write(element, to: proto)
168 }
169 try proto.writeSetEnd()
170 }
171}
172
173extension TSet: CustomStringConvertible, CustomDebugStringConvertible {
174 public var description : String {
175 return storage.description
176 }
177 public var debugDescription : String {
178 return storage.debugDescription
179 }
180
181}
182
183public func ==<Element>(lhs: TSet<Element>, rhs: TSet<Element>) -> Bool {
184 return lhs.storage == rhs.storage
185}