From 4678d403c2dde7e577ada78df89d44d58dd10543 Mon Sep 17 00:00:00 2001 From: Thibault Wittemberg Date: Wed, 2 Feb 2022 20:23:28 +0100 Subject: [PATCH] operators: implement Assign --- README.md | 15 ++++++++++ Sources/Operators/AsyncSequence+Assign.swift | 29 +++++++++++++++++++ .../Operators/AsyncSequence+AssignTests.swift | 29 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 Sources/Operators/AsyncSequence+Assign.swift create mode 100644 Tests/Operators/AsyncSequence+AssignTests.swift diff --git a/README.md b/README.md index 0055444..a29375e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ AsyncSequences * [SwitchToLatest](#SwitchToLatest) * [FlatMapLatest](#FlatMapLatest) * [HandleEvents](#HandleEvents) +* [Assign](#Assign) * [EraseToAnyAsyncSequence](#EraseToAnyAsyncSequence) More operators and extensions are to come. Pull requests are of course welcome. @@ -376,6 +377,20 @@ for try await element in handledSequence {} // finished ``` +### Assign + +`assign(to:on:)` assigns each element from the async sequence to a property on an object. + +```swift +class Root { + var property: String = "" +} + +let root = Root() +let fromSequence = AsyncSequences.From(["1", "2", "3"]) +try await fromSequence.assign(to: \.property, on: root) // will set the property value to "1", "2", "3" +``` + ### EraseToAnyAsyncSequence `eraseToAnyAsyncSequence()` type-erases the async sequence into an AnyAsyncSequence. diff --git a/Sources/Operators/AsyncSequence+Assign.swift b/Sources/Operators/AsyncSequence+Assign.swift new file mode 100644 index 0000000..eab683e --- /dev/null +++ b/Sources/Operators/AsyncSequence+Assign.swift @@ -0,0 +1,29 @@ +// +// AsyncSequence+Assign.swift +// +// +// Created by Thibault Wittemberg on 02/02/2022. +// + +public extension AsyncSequence { + /// Assigns each element from the async sequence to a property on an object. + /// + /// ``` + /// class Root { + /// var property: String = "" + /// } + /// + /// let root = Root() + /// let fromSequence = AsyncSequences.From(["1", "2", "3"]) + /// try await fromSequence.assign(to: \.property, on: root) // will set the property value to "1", "2", "3" + /// ``` + /// + /// - Parameters: + /// - keyPath: A key path that indicates the property to assign. + /// - object: The object that contains the property. + func assign(to keyPath: ReferenceWritableKeyPath, on object: Root) async throws { + for try await element in self { + object[keyPath: keyPath] = element + } + } +} diff --git a/Tests/Operators/AsyncSequence+AssignTests.swift b/Tests/Operators/AsyncSequence+AssignTests.swift new file mode 100644 index 0000000..9a84bf7 --- /dev/null +++ b/Tests/Operators/AsyncSequence+AssignTests.swift @@ -0,0 +1,29 @@ +// +// AsyncSequence+AssignTests.swift +// +// +// Created by Thibault Wittemberg on 02/02/2022. +// + +import AsyncExtensions +import XCTest + +private class Root { + + var successiveValues = [String]() + + var property: String = "" { + didSet { + self.successiveValues.append(self.property) + } + } +} + +final class AsyncSequence_AssignTests: XCTestCase { + func testAssign_sets_elements_on_the_root() async throws { + let root = Root() + let sut = AsyncSequences.From(["1", "2", "3"]) + try await sut.assign(to: \.property, on: root) + XCTAssertEqual(root.successiveValues, ["1", "2", "3"]) + } +}