TM-SGNL-iOS/SignalServiceKit/Util/OrderedSet.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

76 lines
1.9 KiB
Swift

//
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public struct OrderedSet<Element> where Element: Hashable {
public private(set) var orderedMembers: [Element] = []
private var set: Set<Element> = []
public init(_ members: [Element]) {
set = []
orderedMembers = []
for element in members {
append(element)
}
}
@discardableResult
public mutating func append(_ element: Element) -> (Bool, Element) {
let (wasInserted, elementAfterInsert) = set.insert(element)
if wasInserted {
orderedMembers.append(element)
}
return (wasInserted, elementAfterInsert)
}
public mutating func remove(_ element: Element) {
set.remove(element)
orderedMembers = orderedMembers.filter { $0 != element }
}
public mutating func remove(_ elements: [Element]) {
for element in elements {
remove(element)
}
}
public func contains(_ element: Element) -> Bool {
return set.contains(element)
}
public var isEmpty: Bool {
return set.isEmpty
}
public var count: Int {
return set.count
}
public var first: Element? {
return orderedMembers.first
}
public static func == (lhs: OrderedSet<Element>, rhs: OrderedSet<Element>) -> Bool {
lhs.set == rhs.set
}
public static func != (lhs: OrderedSet<Element>, rhs: OrderedSet<Element>) -> Bool {
lhs.set != rhs.set
}
// TODO: I only implemented the minimum API that I needed. There's lots more that could
// reasonably be added to an OrderedSet (union, etc.)
}
extension OrderedSet: ExpressibleByArrayLiteral {
public typealias ArrayLiteralElement = Element
public init(arrayLiteral elements: Element...) {
self.init(elements)
}
}