11/*
2- * Copyright 2025 LiveKit, Inc.
2+ * Copyright 2025-2026 LiveKit, Inc.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616
1717package io.livekit.android.room.datastream.incoming
1818
19+ import io.livekit.android.room.datastream.StreamException
1920import kotlinx.coroutines.channels.Channel
2021import kotlinx.coroutines.flow.Flow
2122import kotlinx.coroutines.flow.catch
2223import kotlinx.coroutines.flow.first
2324import kotlinx.coroutines.flow.fold
2425
26+ /* *
27+ * Base class for reading incoming data streams.
28+ *
29+ * @see [flow]
30+ * @see [readNext]
31+ * @see [readAll]
32+ */
2533abstract class BaseStreamReceiver <T >(private val source : Channel <ByteArray >) {
2634
35+ /* *
36+ * A [Flow] of stream data as it arrives.
37+ *
38+ * Collect this flow to process incoming data incrementally. The flow completes normally when
39+ * the stream receives all the data without error. If the stream ends abnormally, the
40+ * flow fails with a [StreamException] after all buffered chunks have been emitted.
41+ *
42+ * Example:
43+ * ```
44+ * reader.flow
45+ * .catch { e ->
46+ * if (e is StreamException) {
47+ * handleStreamError(e)
48+ * } else {
49+ * throw e
50+ * }
51+ * }
52+ * .collect { chunk -> process(chunk) }
53+ * ```
54+ */
2755 abstract val flow: Flow <T >
2856
2957 internal fun close (error : Exception ? ) {
@@ -34,14 +62,18 @@ abstract class BaseStreamReceiver<T>(private val source: Channel<ByteArray>) {
3462 * Suspends and waits for the next piece of data.
3563 *
3664 * @return the next available piece of data.
37- * @throws NoSuchElementException when the stream is closed and no more data is available.
65+ * @throws NoSuchElementException when the stream is closed normally and no more data is available.
66+ * @throws StreamException when the stream is closed abnormally.
3867 */
3968 suspend fun readNext (): T {
4069 return flow.first()
4170 }
4271
4372 /* *
4473 * Suspends and waits for all available data until the stream is closed.
74+ *
75+ * [StreamException]s are swallowed; this returns all data received before the stream closed,
76+ * whether normally or abnormally.
4577 */
4678 suspend fun readAll (): List <T > {
4779 flow.catch { }
0 commit comments