Skip to content

Commit a37cf48

Browse files
docs(ws-utils): add SampleSource contract documentation and debug_assert
- Document the contract that implementations must return non-empty samples - Add debug_assert to catch contract violations during development - Explain why empty samples are problematic (busy-loop risk) Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
1 parent 3a84d98 commit a37cf48

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

crates/ws-utils/src/buffered_stream.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ impl Default for SampleBuffer {
4747
}
4848
}
4949

50+
/// A source of audio samples for use with [`BufferedAudioStream`].
51+
///
52+
/// # Contract
53+
///
54+
/// Implementations must follow these rules:
55+
///
56+
/// - Return `Poll::Ready(Some(samples))` only when `samples` is **non-empty**.
57+
/// Returning an empty `Vec` violates this contract and may cause busy-looping.
58+
///
59+
/// - Return `Poll::Pending` when no samples are currently available but the
60+
/// stream is not finished. The implementation **must** register the waker
61+
/// from `cx` before returning `Pending` to ensure the task will be woken.
62+
///
63+
/// - Return `Poll::Ready(None)` to signal end of stream.
64+
///
65+
/// # Why empty samples are problematic
66+
///
67+
/// If an implementation returns `Ready(Some(vec![]))`, the wrapper will loop
68+
/// and call `poll_samples` again immediately. If the implementation keeps
69+
/// returning empty samples without ever returning `Pending`, this creates a
70+
/// busy-loop that can starve other tasks on the executor.
5071
pub trait SampleSource {
5172
fn poll_samples(&mut self, cx: &mut Context<'_>) -> Poll<Option<Vec<f32>>>;
5273
}
@@ -82,6 +103,10 @@ impl<S: SampleSource + Unpin> Stream for BufferedAudioStream<S> {
82103

83104
match self.source.poll_samples(cx) {
84105
Poll::Ready(Some(samples)) => {
106+
debug_assert!(
107+
!samples.is_empty(),
108+
"SampleSource returned empty Vec; this violates the trait contract and may cause busy-looping"
109+
);
85110
if samples.is_empty() {
86111
continue;
87112
}

0 commit comments

Comments
 (0)