Coverage Summary for Class: LoggingReceiveChannel (dev.skymansandy.wiretap.plugin.ws.util)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| LoggingReceiveChannel |
57.1%
(4/7)
|
25%
(2/8)
|
64.7%
(11/17)
|
65.5%
(76/116)
|
| LoggingReceiveChannel$iterator$1 |
100%
(3/3)
|
100%
(2/2)
|
100%
(5/5)
|
100%
(48/48)
|
| LoggingReceiveChannel$iterator$1$hasNext$1 |
|
| LoggingReceiveChannel$receive$1 |
|
| LoggingReceiveChannel$receiveCatching$1 |
|
| Total |
70%
(7/10)
|
40%
(4/10)
|
72.7%
(16/22)
|
75.6%
(124/164)
|
/*
* Copyright (c) 2026 skymansandy. All rights reserved.
*/
package dev.skymansandy.wiretap.plugin.ws.util
import io.ktor.websocket.Frame
import kotlinx.coroutines.channels.ChannelIterator
import kotlinx.coroutines.channels.ChannelResult
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.selects.SelectClause1
/**
* Wraps a [ReceiveChannel] to log frames as they are consumed.
* No coroutines are launched — logging is triggered inline on each receive.
*/
internal class LoggingReceiveChannel(
private val delegate: ReceiveChannel<Frame>,
private val logAction: (Frame) -> Unit,
private val onChannelClosed: (Throwable?) -> Unit,
) : ReceiveChannel<Frame> by delegate {
override suspend fun receive(): Frame {
return delegate.receive().also { logAction(it) }
}
override suspend fun receiveCatching(): ChannelResult<Frame> {
return delegate.receiveCatching().also { result ->
result.getOrNull()?.let { logAction(it) }
if (result.isClosed) onChannelClosed(result.exceptionOrNull())
}
}
override fun tryReceive(): ChannelResult<Frame> {
return delegate.tryReceive().also { result ->
result.getOrNull()?.let { logAction(it) }
if (result.isClosed) onChannelClosed(result.exceptionOrNull())
}
}
override fun iterator(): ChannelIterator<Frame> {
val delegateIterator = delegate.iterator()
return object : ChannelIterator<Frame> {
override suspend fun hasNext(): Boolean {
return delegateIterator.hasNext().also { hasMore ->
if (!hasMore) onChannelClosed(null)
}
}
override fun next(): Frame = delegateIterator.next().also { logAction(it) }
}
}
override val onReceive: SelectClause1<Frame>
get() = delegate.onReceive
override val onReceiveCatching: SelectClause1<ChannelResult<Frame>>
get() = delegate.onReceiveCatching
}