@@ -0,0 +1,31 @@ | |||||
import Combine | |||||
public extension Bus { | |||||
final class Async<Src, Dst> { | |||||
let v = PassthroughSubject<Src, Never>() | |||||
var subscriptions = [AnyCancellable]() | |||||
public init( | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ src: String, | |||||
_ dst: String | |||||
) { | |||||
// Вход. | |||||
Bus.receiveSync( | |||||
[src], | |||||
{ [weak self] _, v in self?.v.send(v) }, | |||||
&subscriptions | |||||
) | |||||
// Выход. | |||||
Bus.sendSync( | |||||
dst, | |||||
v | |||||
.compactMap { (v: Src) in handler(v) } | |||||
// Асинхронно. | |||||
.receive(on: DispatchQueue.main) | |||||
.eraseToAnyPublisher(), | |||||
&subscriptions | |||||
) | |||||
} | |||||
} | |||||
} |
@@ -1,5 +1,5 @@ | |||||
public extension Bus { | public extension Bus { | ||||
/// Пропускаем далее предоставленный ключ. | |||||
/// Пропускаем далее единственный ключ. | |||||
static func convertKeyValue<T>( | static func convertKeyValue<T>( | ||||
_ key: String, | _ key: String, | ||||
_ v: (key: String, value: Any) | _ v: (key: String, value: Any) | ||||
@@ -13,7 +13,7 @@ public extension Bus { | |||||
return (key, value) | return (key, value) | ||||
} | } | ||||
/// Пропускаем далее предоставленные ключи. | |||||
/// Пропускаем далее множество ключей. | |||||
static func convertKeyValue<T>( | static func convertKeyValue<T>( | ||||
_ keys: Set<String>, | _ keys: Set<String>, | ||||
_ v: (key: String, value: Any) | _ v: (key: String, value: Any) | ||||
@@ -26,19 +26,4 @@ public extension Bus { | |||||
} | } | ||||
return (v.key, value) | return (v.key, value) | ||||
} | } | ||||
/// Обрабатываем. | |||||
static func processKeysValue<Src, Dst>( | |||||
_ v: (key: String, value: Any), | |||||
_ keysIn: Set<String>, | |||||
_ handler: @escaping ((Src) -> Dst?) | |||||
) -> Dst? { | |||||
guard | |||||
keysIn.contains(v.key), | |||||
let vIn = v.value as? Src | |||||
else { | |||||
return nil | |||||
} | |||||
return handler(vIn) | |||||
} | |||||
} | } |
@@ -1,23 +0,0 @@ | |||||
import Combine | |||||
public extension Bus { | |||||
final class Processor<Src, Dst> { | |||||
var subscriptions = [AnyCancellable]() | |||||
public init( | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ keyIn: String, | |||||
_ keyOut: String | |||||
) { | |||||
Bus.processSync([keyIn], keyOut, handler, &subscriptions) | |||||
} | |||||
public init( | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ keysIn: Set<String>, | |||||
_ keyOut: String | |||||
) { | |||||
Bus.processSync(keysIn, keyOut, handler, &subscriptions) | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
import Combine | |||||
public extension Bus { | |||||
final class Sync<Src, Dst> { | |||||
let v = PassthroughSubject<Src, Never>() | |||||
var subscriptions = [AnyCancellable]() | |||||
public init( | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ src: String, | |||||
_ dst: String | |||||
) { | |||||
// Вход. | |||||
Bus.receiveSync( | |||||
[src], | |||||
{ [weak self] _, v in self?.v.send(v) }, | |||||
&subscriptions | |||||
) | |||||
// Выход. | |||||
Bus.sendSync( | |||||
dst, | |||||
v | |||||
.compactMap { (v: Src) in handler(v) } | |||||
.eraseToAnyPublisher(), | |||||
&subscriptions | |||||
) | |||||
} | |||||
} | |||||
} |
@@ -10,7 +10,7 @@ public enum Bus { | |||||
} | } | ||||
public extension Bus { | public extension Bus { | ||||
/// Асинхронно обрабатывать входящие события из шины. | |||||
/// Асинхронно обрабатываем входящие события из шины. | |||||
static func receiveAsync<T>( | static func receiveAsync<T>( | ||||
_ keys: Set<String>, | _ keys: Set<String>, | ||||
_ handler: @escaping ((String, T) -> Void), | _ handler: @escaping ((String, T) -> Void), | ||||
@@ -23,7 +23,7 @@ public extension Bus { | |||||
.store(in: &subscriptions) | .store(in: &subscriptions) | ||||
} | } | ||||
/// Синхронно обрабатывать входящие события из шины. | |||||
/// Синхронно обрабатываем входящие события из шины. | |||||
static func receiveSync<T>( | static func receiveSync<T>( | ||||
_ keys: Set<String>, | _ keys: Set<String>, | ||||
_ handler: @escaping ((String, T) -> Void), | _ handler: @escaping ((String, T) -> Void), | ||||
@@ -35,19 +35,10 @@ public extension Bus { | |||||
.store(in: &subscriptions) | .store(in: &subscriptions) | ||||
} | } | ||||
/// Асинхронно отправлять события из узла в шину. | |||||
static func sendAsync<T>( | |||||
_ key: String, | |||||
_ node: AnyPublisher<T, Never>, | |||||
_ subscriptions: inout [AnyCancellable] | |||||
) { | |||||
node | |||||
.receive(on: DispatchQueue.main) | |||||
.sink { v in e.send((key, v)) } | |||||
.store(in: &subscriptions) | |||||
} | |||||
/// Синхронно отправлять события из узла в шину. | |||||
/// Синхронно отправляем события из узла в шину. | |||||
/// | |||||
/// Для асинхронной отправки достаточно добавить оператор `receive(on:)` | |||||
/// в цепочке параметра `node` | |||||
static func sendSync<T>( | static func sendSync<T>( | ||||
_ key: String, | _ key: String, | ||||
_ node: AnyPublisher<T, Never>, | _ node: AnyPublisher<T, Never>, | ||||
@@ -58,35 +49,8 @@ public extension Bus { | |||||
.store(in: &subscriptions) | .store(in: &subscriptions) | ||||
} | } | ||||
/// Синхронно отправить событие в шину один раз. | |||||
/// Единоразово синхронно отправляем событие в шину. | |||||
static func send(_ key: String, _ value: Any) { | static func send(_ key: String, _ value: Any) { | ||||
e.send((key, value)) | e.send((key, value)) | ||||
} | } | ||||
} | } | ||||
public extension Bus { | |||||
static func processAsync<Src, Dst>( | |||||
_ keysIn: Set<String>, | |||||
_ keyOut: String, | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ subscriptions: inout [AnyCancellable] | |||||
) { | |||||
e | |||||
.compactMap { processKeysValue($0, keysIn, handler) } | |||||
.receive(on: DispatchQueue.main) | |||||
.sink { vOut in Self.e.send((keyOut, vOut)) } | |||||
.store(in: &subscriptions) | |||||
} | |||||
static func processSync<Src, Dst>( | |||||
_ keysIn: Set<String>, | |||||
_ keyOut: String, | |||||
_ handler: @escaping ((Src) -> Dst?), | |||||
_ subscriptions: inout [AnyCancellable] | |||||
) { | |||||
e | |||||
.compactMap { processKeysValue($0, keysIn, handler) } | |||||
.sink { vOut in Self.e.send((keyOut, vOut)) } | |||||
.store(in: &subscriptions) | |||||
} | |||||
} |
@@ -8,7 +8,7 @@ extension MeetupId { | |||||
@StateObject var join = BusUI.Button(K.join) | @StateObject var join = BusUI.Button(K.join) | ||||
@StateObject var textField = BusUI.TextField(K.textApp, K.textUI) | @StateObject var textField = BusUI.TextField(K.textApp, K.textUI) | ||||
let processors: [Any] = [ | let processors: [Any] = [ | ||||
Bus.Processor(shouldEnableJoin, K.M, K.isJoinAvailable), | |||||
Bus.Sync(shouldEnableJoin, K.M, K.isJoinAvailable), | |||||
MeetupId.Debounce(0.2, formatId, K.textUI, K.textApp), | MeetupId.Debounce(0.2, formatId, K.textUI, K.textApp), | ||||
MeetupId.Delay(5, finishLoading, K.isLoading, K.finishLoading), | MeetupId.Delay(5, finishLoading, K.isLoading, K.finishLoading), | ||||
] | ] | ||||