forked from CombineCommunity/CombineExt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4a9b16c
commit 309d427
Showing
5 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// | ||
// Nwise.swift | ||
// CombineExt | ||
// | ||
// Created by Bas van Kuijck on 14/08/2020. | ||
// Copyright © 2020 Combine Community. All rights reserved. | ||
// | ||
|
||
#if canImport(Combine) | ||
import Combine | ||
|
||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) | ||
public extension Publisher { | ||
/// Groups the elements of the source publisher into arrays of N consecutive elements. | ||
/// The resulting publisher: | ||
/// - does not emit anything until the source publisher emits at least N elements; | ||
/// - emits an array for every element after that; | ||
/// - forwards any errors or completed events. | ||
/// | ||
/// - parameter size: size of the groups, must be greater than 1 | ||
/// | ||
/// - returns: A type erased publisher that holds an array with the given size. | ||
func nwise(_ size: Int) -> AnyPublisher<[Output], Failure> { | ||
assert(size > 1, "n must be greater than 1") | ||
|
||
return scan([]) { acc, item in Array((acc + [item]).suffix(size)) } | ||
.filter { $0.count == size } | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
/// Groups the elements of the source publisher into tuples of the previous and current elements | ||
/// The resulting publisher: | ||
/// - does not emit anything until the source publisher emits at least 2 elements; | ||
/// - emits a tuple for every element after that, consisting of the previous and the current item; | ||
/// - forwards any error or completed events. | ||
/// | ||
/// - returns: A type erased publisher that holds a tuple with 2 elements. | ||
func pairwise() -> AnyPublisher<(Output, Output), Failure> { | ||
return nwise(2) | ||
.map { ($0[0], $0[1]) } | ||
.eraseToAnyPublisher() | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// | ||
// CurrentValueRelayTests.swift | ||
// CombineExtTests | ||
// | ||
// Created by Bas van Kuijck on 14/08/2020. | ||
// Copyright © 2020 Combine Community. All rights reserved. | ||
// | ||
|
||
#if !os(watchOS) | ||
import XCTest | ||
import Combine | ||
import CombineExt | ||
|
||
private struct PairwiseTuple<T: Equatable>: Equatable { | ||
let element1: T | ||
let element2: T | ||
|
||
init(_ tuple: (T, T)) { | ||
element1 = tuple.0 | ||
element2 = tuple.1 | ||
} | ||
|
||
init(_ element1: T, _ element2: T) { | ||
self.element1 = element1 | ||
self.element2 = element2 | ||
} | ||
|
||
static func == (lhs: PairwiseTuple<T>, rhs: PairwiseTuple<T>) -> Bool { | ||
return lhs.element1 == rhs.element1 && lhs.element2 == rhs.element2 | ||
} | ||
} | ||
|
||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) | ||
class NwiseTests: XCTestCase { | ||
private var subscriptions = Set<AnyCancellable>() | ||
|
||
func testNwise() { | ||
var expectedOutput: [[Int]] = [] | ||
var completion: Subscribers.Completion<Never>? | ||
|
||
Publishers.Sequence(sequence: [1, 2, 3, 4, 5, 6]) | ||
.nwise(3) | ||
.sink( | ||
receiveCompletion: { completion = $0 }, | ||
receiveValue: { expectedOutput.append($0) } | ||
).store(in: &subscriptions) | ||
|
||
XCTAssertEqual( | ||
expectedOutput, | ||
[ | ||
[1, 2, 3], | ||
[2, 3, 4], | ||
[3, 4, 5], | ||
[4, 5, 6] | ||
] | ||
) | ||
XCTAssertEqual(completion, .finished) | ||
} | ||
|
||
func testNwiseNone() { | ||
var completion: Subscribers.Completion<Never>? | ||
|
||
Publishers.Sequence(sequence: [1, 2, 3]) | ||
.nwise(4) | ||
.sink( | ||
receiveCompletion: { completion = $0 }, | ||
receiveValue: { XCTAssert(false, "Should not receive a value, got \($0)") } | ||
).store(in: &subscriptions) | ||
|
||
XCTAssertEqual(completion, .finished) | ||
} | ||
|
||
func testPairwise() { | ||
var expectedOutput: [PairwiseTuple<Int>] = [] | ||
var completion: Subscribers.Completion<Never>? | ||
|
||
Publishers.Sequence(sequence: [1, 2, 3, 4, 5, 6]) | ||
.pairwise() | ||
.sink( | ||
receiveCompletion: { completion = $0 }, | ||
receiveValue: { expectedOutput.append(PairwiseTuple($0)) } | ||
).store(in: &subscriptions) | ||
|
||
XCTAssertEqual( | ||
expectedOutput, | ||
[ | ||
PairwiseTuple(1, 2), | ||
PairwiseTuple(2, 3), | ||
PairwiseTuple(3, 4), | ||
PairwiseTuple(4, 5), | ||
PairwiseTuple(5, 6), | ||
] | ||
) | ||
XCTAssertEqual(completion, .finished) | ||
} | ||
|
||
} | ||
#endif |