diff --git a/Package.swift b/Package.swift index 130288daa..30abb74ba 100644 --- a/Package.swift +++ b/Package.swift @@ -227,6 +227,8 @@ let targets: [CustomTarget] = [ kind: .test, name: "DequeTests", dependencies: ["DequeModule", "_CollectionsTestSupport"]), + + .target(kind: .exported, name: "DictionaryProtocol"), .target( kind: .exported, @@ -251,7 +253,7 @@ let targets: [CustomTarget] = [ .target( kind: .exported, name: "OrderedCollections", - dependencies: ["_CollectionsUtilities"], + dependencies: ["_CollectionsUtilities", "DictionaryProtocol"], exclude: ["CMakeLists.txt"]), .target( kind: .test, diff --git a/Sources/DictionaryProtocol/DictionaryConformance.swift b/Sources/DictionaryProtocol/DictionaryConformance.swift new file mode 100644 index 000000000..f3c2ef068 --- /dev/null +++ b/Sources/DictionaryProtocol/DictionaryConformance.swift @@ -0,0 +1,4 @@ +extension Dictionary: DictionaryProtocol { + public typealias Elements = Self + public var elements: Elements { self } +} diff --git a/Sources/DictionaryProtocol/DictionaryProtocol.swift b/Sources/DictionaryProtocol/DictionaryProtocol.swift new file mode 100644 index 000000000..f7b54a68d --- /dev/null +++ b/Sources/DictionaryProtocol/DictionaryProtocol.swift @@ -0,0 +1,48 @@ +public protocol DictionaryProtocol: Sequence, ExpressibleByDictionaryLiteral where Element == (key: Key, value: Value), Key: Hashable { + associatedtype Key + associatedtype Value + + associatedtype Keys: Collection where Keys.Element == Key + associatedtype Values: Collection where Values.Element == Value + associatedtype Elements: Collection where Elements.Element == Element + + var keys: Keys { get } + var values: Values { get } + var elements: Elements { get } + + subscript(key: Key) -> Value? { get } + + init() + + // Cannot implement since stdlib's Dictionary has a different signature (unlabelled tuple) + //init(uniqueKeysWithValues keysAndValues: S) where S.Element == (key: Key, value: Value) + + init(uniqueKeysWithValues keysAndValues: S) where S.Element == (Key, Value) + + init( + _ keysAndValues: S, + uniquingKeysWith combine: (Value, Value) throws -> Value + ) rethrows where S.Element == (Key, Value) + + // OrderedDictionary also has a more generic version of this with the where clause: `where Value: RangeReplaceableCollection, Value.Element == S.Element` instead of `Value == [S.Element]` + init( + grouping values: S, + by keyForValue: (S.Element) throws -> Key + ) rethrows where Value == [S.Element] + + init(_ other: some DictionaryProtocol) + + // does not work for stdlib Dictionary. Not sure how to capture stdlib Dictionary signature for this method in protocol + //func mapValues(_ transform: (Value) throws -> T) rethrows -> Result where Result.Value == T + // func compactMapValues // same as above + + func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> Self +} + +extension DictionaryProtocol { + // This does not guarantee any sort of ordering when using `OrderedDictionary` however... + public init(_ other: some DictionaryProtocol) { + // .lazy.map in order to remove labels from tuple + self.init(uniqueKeysWithValues: other.elements.lazy.map { $0 }) + } +} diff --git a/Sources/DictionaryProtocol/MutableDictionaryProtocol.swift b/Sources/DictionaryProtocol/MutableDictionaryProtocol.swift new file mode 100644 index 000000000..0ad35c628 --- /dev/null +++ b/Sources/DictionaryProtocol/MutableDictionaryProtocol.swift @@ -0,0 +1,7 @@ +protocol MutableDictionaryProtocol: DictionaryProtocol { + var values: Values { get set } + var elements: Elements { get set } + + mutating func updateValue(_ value: Value, forKey key: Key) -> Value? + mutating func removeValue(forKey key: Key) -> Value? +} diff --git a/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift b/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift index 14e37fb93..10c0eaaea 100644 --- a/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift +++ b/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift @@ -9,6 +9,8 @@ // //===----------------------------------------------------------------------===// +import DictionaryProtocol + /// An ordered collection of key-value pairs. /// /// Like the standard `Dictionary`, ordered dictionaries use a hash table to @@ -218,6 +220,8 @@ public struct OrderedDictionary { } } +extension OrderedDictionary: DictionaryProtocol { } + extension OrderedDictionary { /// A read-only ordered collection view for the keys contained in this dictionary, as /// an `OrderedSet`.