Skip to content

Commit

Permalink
Introduce generalized _ValueUpdateWrapping for ValueStore and Synchro…
Browse files Browse the repository at this point in the history
…nized
  • Loading branch information
Alkenso committed Dec 10, 2024
1 parent c775bb9 commit 585580f
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 64 deletions.
100 changes: 100 additions & 0 deletions Sources/SpellbookFoundation/Private/_ValueUpdateWrapping.swift
Original file line number Diff line number Diff line change
@@ -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<R>(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: Hashable>(
_ element: Element
) -> (inserted: Bool, memberAfterInsert: Element) where Value == Set<Element> {
_updateValue { $0.insert(element) }
}

@discardableResult
public func remove<Element: Hashable>(
_ element: Element
) -> Element? where Value == Set<Element> {
_updateValue { $0.remove(element) }
}

public func popFirst<Element: Hashable>() -> Element? where Value == Set<Element> {
_updateValue { $0.popFirst() }
}

public func formUnion<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
_updateValue { $0.formUnion(other) }
}

public func subtract<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
_updateValue { $0.subtract(other) }
}

public func formIntersection<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
_updateValue { $0.formIntersection(other) }
}

public func formSymmetricDifference<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
_updateValue { $0.formSymmetricDifference(other) }
}
}

extension _ValueUpdateWrapping {
public func popFirst<Key: Hashable, Element>() -> Value.Element? where Value == [Key: Element] {
_updateValue { $0.popFirst() }
}

@discardableResult
public func updateValue<Key: Hashable, Element>(
_ value: Element, forKey key: Key
) -> Element? where Value == [Key: Element] {
_updateValue { $0.updateValue(value, forKey: key) }
}

@discardableResult
public func removeValue<Key: Hashable, Element>(forKey key: Key) -> Element? where Value == [Key: Element] {
_updateValue { $0.removeValue(forKey: key) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ extension Synchronized {
}
}

extension Synchronized: _ValueUpdateWrapping {
public func _updateValue<R>(body: (inout Value) -> R) -> R {
write(body)
}
}

public extension Synchronized where Value: AdditiveArithmetic {
static func + (lhs: Synchronized, rhs: Value) -> Value {
lhs.read() + rhs
Expand Down
70 changes: 6 additions & 64 deletions Sources/SpellbookFoundation/ValueObserving/ValueStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Element: Hashable>() where Value == Set<Element> {
self.init(initialValue: [])
}

@discardableResult
public func insert<Element: Hashable>(
_ element: Element
) -> (inserted: Bool, memberAfterInsert: Element) where Value == Set<Element> {
update { $0.insert(element) }
}

@discardableResult
public func remove<Element: Hashable>(_ element: Element) -> Element? where Value == Set<Element> {
update { $0.remove(element) }
}

public func popFirst<Element: Hashable>() -> Element? where Value == Set<Element> {
update { $0.popFirst() }
}

public func formUnion<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
update { $0.formUnion(other) }
}

public func subtract<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
update { $0.subtract(other) }
}

public func formIntersection<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
update { $0.formIntersection(other) }
}

public func formSymmetricDifference<Element: Hashable, S>(
_ other: S
) where Value == Set<Element>, S: Sequence, Element == S.Element {
update { $0.formSymmetricDifference(other) }
public convenience init() where Value: ExpressibleByDictionaryLiteral {
self.init(initialValue: [:])
}
}

extension ValueStore {
public func popFirst<Key: Hashable, Element>() -> Value.Element? where Value == [Key: Element] {
update { $0.popFirst() }
}

@discardableResult
public func updateValue<Key: Hashable, Element>(
_ value: Element, forKey key: Key
) -> Element? where Value == [Key: Element] {
update { $0.updateValue(value, forKey: key) }
}

@discardableResult
public func removeValue<Key: Hashable, Element>(forKey key: Key) -> Element? where Value == [Key: Element] {
update { $0.removeValue(forKey: key) }

extension ValueStore: _ValueUpdateWrapping {
public func _updateValue<R>(body: (inout Value) -> R) -> R {
update(body: body)
}
}

0 comments on commit 585580f

Please sign in to comment.