From 585580f18811e79db0529fb4f8aa1494f634606b Mon Sep 17 00:00:00 2001 From: "Alkenso (Vladimir Vashurkin)" Date: Tue, 10 Dec 2024 05:28:20 +0200 Subject: [PATCH] Introduce generalized _ValueUpdateWrapping for ValueStore and Synchronized --- .../Private/_ValueUpdateWrapping.swift | 100 ++++++++++++++++++ .../Synchronized.swift | 6 ++ .../ValueObserving/ValueStore.swift | 70 ++---------- 3 files changed, 112 insertions(+), 64 deletions(-) create mode 100644 Sources/SpellbookFoundation/Private/_ValueUpdateWrapping.swift diff --git a/Sources/SpellbookFoundation/Private/_ValueUpdateWrapping.swift b/Sources/SpellbookFoundation/Private/_ValueUpdateWrapping.swift new file mode 100644 index 0000000..6bbd22d --- /dev/null +++ b/Sources/SpellbookFoundation/Private/_ValueUpdateWrapping.swift @@ -0,0 +1,100 @@ +// MIT License +// +// Copyright (c) 2024 Alkenso (Vladimir Vashurkin) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation + +public protocol _ValueUpdateWrapping { + associatedtype Value + @_spi(Private) func _updateValue(body: (inout Value) -> R) -> R +} + +extension _ValueUpdateWrapping { + public func append(_ element: Value.Element) where Value: RangeReplaceableCollection { + _updateValue { $0.append(element) } + } + + public func removeAll(where shouldBeRemoved: (Value.Element) -> Bool) where Value: RangeReplaceableCollection { + _updateValue { $0.removeAll(where: shouldBeRemoved) } + } +} + +extension _ValueUpdateWrapping { + @discardableResult + public func insert( + _ element: Element + ) -> (inserted: Bool, memberAfterInsert: Element) where Value == Set { + _updateValue { $0.insert(element) } + } + + @discardableResult + public func remove( + _ element: Element + ) -> Element? where Value == Set { + _updateValue { $0.remove(element) } + } + + public func popFirst() -> Element? where Value == Set { + _updateValue { $0.popFirst() } + } + + public func formUnion( + _ other: S + ) where Value == Set, S: Sequence, Element == S.Element { + _updateValue { $0.formUnion(other) } + } + + public func subtract( + _ other: S + ) where Value == Set, S: Sequence, Element == S.Element { + _updateValue { $0.subtract(other) } + } + + public func formIntersection( + _ other: S + ) where Value == Set, S: Sequence, Element == S.Element { + _updateValue { $0.formIntersection(other) } + } + + public func formSymmetricDifference( + _ other: S + ) where Value == Set, S: Sequence, Element == S.Element { + _updateValue { $0.formSymmetricDifference(other) } + } +} + +extension _ValueUpdateWrapping { + public func popFirst() -> Value.Element? where Value == [Key: Element] { + _updateValue { $0.popFirst() } + } + + @discardableResult + public func updateValue( + _ value: Element, forKey key: Key + ) -> Element? where Value == [Key: Element] { + _updateValue { $0.updateValue(value, forKey: key) } + } + + @discardableResult + public func removeValue(forKey key: Key) -> Element? where Value == [Key: Element] { + _updateValue { $0.removeValue(forKey: key) } + } +} diff --git a/Sources/SpellbookFoundation/Threading & Concurrency/Synchronized.swift b/Sources/SpellbookFoundation/Threading & Concurrency/Synchronized.swift index c67bfa5..a9a2155 100644 --- a/Sources/SpellbookFoundation/Threading & Concurrency/Synchronized.swift +++ b/Sources/SpellbookFoundation/Threading & Concurrency/Synchronized.swift @@ -129,6 +129,12 @@ extension Synchronized { } } +extension Synchronized: _ValueUpdateWrapping { + public func _updateValue(body: (inout Value) -> R) -> R { + write(body) + } +} + public extension Synchronized where Value: AdditiveArithmetic { static func + (lhs: Synchronized, rhs: Value) -> Value { lhs.read() + rhs diff --git a/Sources/SpellbookFoundation/ValueObserving/ValueStore.swift b/Sources/SpellbookFoundation/ValueObserving/ValueStore.swift index e85727c..6b55629 100644 --- a/Sources/SpellbookFoundation/ValueObserving/ValueStore.swift +++ b/Sources/SpellbookFoundation/ValueObserving/ValueStore.swift @@ -229,75 +229,17 @@ extension ValueStore { self.init(initialValue: []) } - public func append(_ element: Value.Element) where Value: RangeReplaceableCollection { - update { $0.append(element) } - } - - public func removeAll(where shouldBeRemoved: (Value.Element) -> Bool) where Value: RangeReplaceableCollection { - update { $0.removeAll(where: shouldBeRemoved) } - } -} - -extension ValueStore { public convenience init() where Value == Set { self.init(initialValue: []) } - @discardableResult - public func insert( - _ element: Element - ) -> (inserted: Bool, memberAfterInsert: Element) where Value == Set { - update { $0.insert(element) } - } - - @discardableResult - public func remove(_ element: Element) -> Element? where Value == Set { - update { $0.remove(element) } - } - - public func popFirst() -> Element? where Value == Set { - update { $0.popFirst() } - } - - public func formUnion( - _ other: S - ) where Value == Set, S: Sequence, Element == S.Element { - update { $0.formUnion(other) } - } - - public func subtract( - _ other: S - ) where Value == Set, S: Sequence, Element == S.Element { - update { $0.subtract(other) } - } - - public func formIntersection( - _ other: S - ) where Value == Set, S: Sequence, Element == S.Element { - update { $0.formIntersection(other) } - } - - public func formSymmetricDifference( - _ other: S - ) where Value == Set, S: Sequence, Element == S.Element { - update { $0.formSymmetricDifference(other) } + public convenience init() where Value: ExpressibleByDictionaryLiteral { + self.init(initialValue: [:]) } } - -extension ValueStore { - public func popFirst() -> Value.Element? where Value == [Key: Element] { - update { $0.popFirst() } - } - - @discardableResult - public func updateValue( - _ value: Element, forKey key: Key - ) -> Element? where Value == [Key: Element] { - update { $0.updateValue(value, forKey: key) } - } - - @discardableResult - public func removeValue(forKey key: Key) -> Element? where Value == [Key: Element] { - update { $0.removeValue(forKey: key) } + +extension ValueStore: _ValueUpdateWrapping { + public func _updateValue(body: (inout Value) -> R) -> R { + update(body: body) } }