You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.5 KiB

5 years ago
  1. //
  2. // and.swift
  3. // RxSwiftExt
  4. //
  5. // Created by Florent Pillet on 26/11/17.
  6. // Copyright © 2017 RxSwift Community. All rights reserved.
  7. //
  8. import Foundation
  9. import RxSwift
  10. extension ObservableType where E == Bool {
  11. /**
  12. Emits a single Bool value indicating whether or not a Bool sequence emits only `true` values.
  13. If a `false` value is emitted, the resulting sequence immediately completes with a `false` result.
  14. If only `true` values are emitted, the resulting sequence completes with a `true` result once the
  15. source sequence completes.
  16. If no value is emitted, the resulting sequence completes with no value once the source sequence completes.
  17. Use `asSingle()` or `asObservable()` to convert to your requirements.
  18. */
  19. public func and() -> Maybe<E> {
  20. return Maybe.create { observer in
  21. var gotValue = false
  22. return self.subscribe { event in
  23. switch event {
  24. case .next(let value):
  25. if !value {
  26. // first `false` value emits false & completes
  27. observer(.success(false))
  28. } else {
  29. gotValue = true
  30. }
  31. case .error(let error):
  32. observer(.error(error))
  33. case .completed:
  34. observer(gotValue ? .success(true) : .completed)
  35. }
  36. }
  37. }
  38. }
  39. /**
  40. Emits a single Bool value indicating whether or not a each Bool sequence in the collection emits only `true` values.
  41. Each sequence of the collection is expected to emit at least one `true` value.
  42. If any sequence does not emit anything, the produced `Maybe` will just complete.
  43. If any sequence emits a `false` value, the produiced `Maybe` will emit a `false` result.
  44. If all sequences emit at least one `true` value, the produced `Maybe` will emit a `true` result.
  45. Use `asSingle()` or `asObservable()` to convert to your requirements.
  46. */
  47. public static func and<C: Collection>(_ collection: C) -> Maybe<E> where C.Element: ObservableType, C.Element.E == E {
  48. return Maybe.create { observer in
  49. var emitted = [Bool](repeating: false, count: Int(collection.count))
  50. var completed = 0
  51. let lock = NSRecursiveLock()
  52. lock.lock()
  53. defer { lock.unlock() }
  54. let subscriptions = collection.enumerated().map { item in
  55. item.element.subscribe { event in
  56. lock.lock()
  57. defer { lock.unlock() }
  58. switch event {
  59. case .next(let value):
  60. if !value {
  61. // first `false` value emits false & completes
  62. observer(.success(false))
  63. } else {
  64. emitted[item.offset] = true
  65. }
  66. case .error(let error):
  67. observer(.error(error))
  68. case .completed:
  69. completed += 1
  70. guard completed == collection.count else { return }
  71. // if all emitted at least one `true`, emit true otherwise just complete
  72. if emitted.reduce(true, { $0 && $1 }) {
  73. observer(.success(true))
  74. } else {
  75. observer(.completed)
  76. }
  77. }
  78. }
  79. }
  80. return CompositeDisposable(disposables: subscriptions)
  81. }
  82. }
  83. /**
  84. Emits a single Bool value indicating whether or not a each Bool sequence in the collection emits only `true` values.
  85. Each sequence of the collection is expected to emit at least one `true` value.
  86. If any sequence does not emit anything, the produced `Maybe` will just complete.
  87. If any sequence emits a `false` value, the produiced `Maybe` will emit a `false` result.
  88. If all sequences emit at least one `true` value, the produced `Maybe` will emit a `true` result.
  89. Use `asSingle()` or `asObservable()` to convert to your requirements.
  90. */
  91. public static func and<O: ObservableType>(_ sources: O ...) -> Maybe<E> where O.E == E {
  92. return and(sources)
  93. }
  94. }