1use std::sync::Arc;
9use std::sync::OnceLock;
10use std::sync::atomic::{AtomicUsize, Ordering};
11use std::task::{Poll, ready};
12
13use arrayvec::ArrayVec;
14use bytes::Bytes;
15
16use crate::group::{self, GroupState};
17use crate::{Error, IntoBytes, Result, Timestamp, stats};
18
19#[derive(Clone, Copy, Debug)]
24pub struct Info {
25 pub size: u64,
27 pub timestamp: Timestamp,
33}
34
35#[derive(Clone, Debug)]
40pub struct Frame {
41 pub timestamp: Timestamp,
43 pub payload: Bytes,
45}
46
47#[derive(Debug, Default)]
69pub struct Buffer<const N: usize = 8>(ArrayVec<Frame, N>);
70
71impl<const N: usize> Buffer<N> {
72 pub fn new() -> Self {
74 Self(ArrayVec::new())
75 }
76
77 pub const fn capacity(&self) -> usize {
79 N
80 }
81
82 pub fn len(&self) -> usize {
84 self.0.len()
85 }
86
87 pub fn is_empty(&self) -> bool {
89 self.0.is_empty()
90 }
91
92 pub fn is_full(&self) -> bool {
94 self.0.is_full()
95 }
96
97 pub fn filled(&self) -> &[Frame] {
99 &self.0
100 }
101
102 pub fn filled_mut(&mut self) -> &mut [Frame] {
104 &mut self.0
105 }
106
107 pub fn push(&mut self, frame: Frame) -> std::result::Result<(), Frame> {
112 self.0.try_push(frame).map_err(|err| err.element())
113 }
114
115 pub fn drain(&mut self) -> impl ExactSizeIterator<Item = Frame> + '_ {
120 self.0.drain(..)
121 }
122
123 pub fn clear(&mut self) {
125 self.0.clear();
126 }
127
128 pub(crate) fn fill(&mut self, frames: impl Iterator<Item = Frame>) -> usize {
131 debug_assert!(self.is_empty(), "fill on a non-empty buffer would drop frames");
132 self.0.extend(frames.take(N));
133 self.len()
134 }
135}
136
137#[derive(Clone)]
146pub(crate) struct FrameBuf(Arc<FrameBufInner>);
147
148struct FrameBufInner {
149 capacity: usize,
150 written: AtomicUsize,
151 storage: OnceLock<FrameStorage>,
152}
153
154enum FrameStorage {
155 Shared(Bytes),
156 Mutable(MutableFrameBuf),
157}
158
159struct MutableFrameBuf {
160 data: *mut u8,
162 capacity: usize,
163}
164
165unsafe impl Send for MutableFrameBuf {}
168unsafe impl Sync for MutableFrameBuf {}
169
170impl Drop for MutableFrameBuf {
171 fn drop(&mut self) {
172 unsafe {
175 let slice = std::ptr::slice_from_raw_parts_mut(self.data, self.capacity);
176 drop(Box::from_raw(slice));
177 }
178 }
179}
180
181impl MutableFrameBuf {
182 fn new(size: usize) -> Self {
183 let boxed: Box<[u8]> = vec![0u8; size].into_boxed_slice();
184 let capacity = boxed.len();
185 let data = Box::into_raw(boxed) as *mut u8;
186 Self { data, capacity }
187 }
188}
189
190impl FrameBuf {
191 pub(crate) fn new(size: usize) -> Self {
196 Self(Arc::new(FrameBufInner {
197 capacity: size,
198 written: AtomicUsize::new(0),
199 storage: OnceLock::new(),
200 }))
201 }
202
203 pub(crate) fn capacity(&self) -> usize {
204 self.0.capacity
205 }
206
207 pub(crate) fn written(&self, ord: Ordering) -> usize {
208 self.0.written.load(ord)
209 }
210
211 fn try_set_bytes(&self, bytes: Bytes) -> std::result::Result<(), Bytes> {
212 if bytes.len() != self.capacity() || self.written(Ordering::Acquire) != 0 {
213 return Err(bytes);
214 }
215 self.0
216 .storage
217 .set(FrameStorage::Shared(bytes))
218 .map_err(|storage| match storage {
219 FrameStorage::Shared(bytes) => bytes,
220 FrameStorage::Mutable(_) => unreachable!("try_set_bytes only installs shared storage"),
221 })
222 }
223
224 fn mutable(&self) -> Option<&MutableFrameBuf> {
228 match self
229 .0
230 .storage
231 .get_or_init(|| FrameStorage::Mutable(MutableFrameBuf::new(self.capacity())))
232 {
233 FrameStorage::Shared(_) => None,
234 FrameStorage::Mutable(buf) => Some(buf),
235 }
236 }
237
238 unsafe fn store_written(&self, new_written: usize) {
240 self.0.written.store(new_written, Ordering::Release);
242 }
243
244 fn append(&self, src: &[u8]) {
250 if src.is_empty() {
251 return;
252 }
253 let prev = self.written(Ordering::Relaxed);
254 let Some(buf) = self.mutable() else {
255 return;
258 };
259 unsafe {
262 std::ptr::copy_nonoverlapping(src.as_ptr(), buf.data.add(prev), src.len());
263 self.store_written(prev + src.len());
264 }
265 }
266
267 fn freeze(&self, size: usize) -> Bytes {
272 match self.0.storage.get() {
273 Some(FrameStorage::Shared(bytes)) => bytes.clone(),
274 _ => self.slice(0, size),
275 }
276 }
277
278 fn slice(&self, start: usize, end: usize) -> Bytes {
280 Bytes::from_owner(self.clone()).slice(start..end)
281 }
282}
283
284impl AsRef<[u8]> for FrameBuf {
285 fn as_ref(&self) -> &[u8] {
286 let written = self.0.written.load(Ordering::Acquire);
289 match self.0.storage.get() {
290 Some(FrameStorage::Shared(bytes)) => &bytes[..written],
291 Some(FrameStorage::Mutable(buf)) => {
292 unsafe { std::slice::from_raw_parts(buf.data, written) }
296 }
297 None => &[],
298 }
299 }
300}
301
302pub struct Producer<'a> {
313 group: &'a mut group::Producer,
314 buf: FrameBuf,
315 info: Info,
316 done: bool,
318 stats: stats::Meter,
321}
322
323impl std::ops::Deref for Producer<'_> {
324 type Target = Info;
325
326 fn deref(&self) -> &Self::Target {
327 &self.info
328 }
329}
330
331impl<'a> Producer<'a> {
332 pub(crate) fn new(group: &'a mut group::Producer, buf: FrameBuf, info: Info) -> Self {
333 Self {
334 group,
335 buf,
336 info,
337 done: false,
338 stats: stats::Meter::default(),
339 }
340 }
341
342 pub(crate) fn with_meter(mut self, meter: stats::Meter) -> Self {
344 self.stats = meter;
345 self
346 }
347
348 pub fn group(&self) -> group::Info {
350 self.group.info()
351 }
352
353 pub fn remaining(&self) -> usize {
355 self.buf.capacity() - self.buf.written(Ordering::Acquire)
356 }
357
358 pub fn write<B: IntoBytes>(&mut self, chunk: B) -> Result<()> {
362 let len = chunk.as_ref().len();
363 if len > self.remaining() {
364 return Err(Error::WrongSize);
365 }
366 self.stats.bytes(len as u64);
368 if len == self.buf.capacity() && self.buf.written(Ordering::Acquire) == 0 {
370 match self.buf.try_set_bytes(chunk.into_bytes()) {
371 Ok(()) => {
372 let cap = self.buf.capacity();
373 unsafe { self.buf.store_written(cap) };
376 }
377 Err(chunk) => self.buf.append(&chunk),
378 }
379 } else {
380 self.buf.append(chunk.as_ref());
381 }
382 self.group.frame_notify();
383 Ok(())
384 }
385
386 pub fn finish(mut self) -> Result<()> {
390 if self.buf.written(Ordering::Acquire) != self.buf.capacity() {
391 return Err(Error::WrongSize);
392 }
393 let payload = self.buf.freeze(self.buf.capacity());
394 self.group.frame_commit(Frame {
395 timestamp: self.info.timestamp,
396 payload,
397 })?;
398 self.done = true;
399 Ok(())
400 }
401
402 pub fn abort(mut self, err: Error) -> Result<()> {
404 self.group.frame_abort(err);
405 self.done = true;
406 Ok(())
407 }
408}
409
410impl Drop for Producer<'_> {
411 fn drop(&mut self) {
412 if !self.done {
413 tracing::warn!(
416 group = self.group.info().sequence,
417 "frame::Producer dropped before writing all bytes"
418 );
419 self.group.frame_abort(Error::Dropped);
420 }
421 }
422}
423
424#[derive(Clone)]
427pub(crate) enum Source {
428 Complete(Bytes),
429 Partial(FrameBuf),
430}
431
432#[derive(Clone)]
438pub struct Consumer {
439 state: kio::Consumer<GroupState>,
441 info: Info,
442 source: Source,
443 read_idx: usize,
445 stats: stats::Meter,
448}
449
450impl std::ops::Deref for Consumer {
451 type Target = Info;
452
453 fn deref(&self) -> &Self::Target {
454 &self.info
455 }
456}
457
458impl Consumer {
459 pub(crate) fn new(state: kio::Consumer<GroupState>, info: Info, source: Source) -> Self {
460 Self {
461 state,
462 info,
463 source,
464 read_idx: 0,
465 stats: stats::Meter::default(),
466 }
467 }
468
469 pub(crate) fn with_meter(mut self, meter: stats::Meter) -> Self {
472 self.stats = meter;
473 self
474 }
475
476 pub fn poll_read_chunk(&mut self, waiter: &kio::Waiter) -> Poll<Result<Option<Bytes>>> {
480 match &self.source {
481 Source::Complete(bytes) => {
482 if self.read_idx >= bytes.len() {
483 return Poll::Ready(Ok(None));
484 }
485 let out = bytes.slice(self.read_idx..);
486 self.read_idx = bytes.len();
487 self.stats.bytes(out.len() as u64);
488 Poll::Ready(Ok(Some(out)))
489 }
490 Source::Partial(buf) => {
491 let buf = buf.clone();
492 let size = self.info.size as usize;
493 loop {
494 let written = buf.written(Ordering::Acquire);
495 if written > self.read_idx {
496 let out = buf.slice(self.read_idx, written);
497 self.read_idx = written;
498 self.stats.bytes(out.len() as u64);
499 return Poll::Ready(Ok(Some(out)));
500 }
501 if written >= size {
502 return Poll::Ready(Ok(None));
503 }
504 let read_idx = self.read_idx;
505 ready!(poll_state(&self.state, waiter, |state| {
508 if let Some(err) = &state.abort {
509 return Poll::Ready(Err(err.clone()));
510 }
511 let w = buf.written(Ordering::Acquire);
512 if w > read_idx || w >= size {
513 Poll::Ready(Ok(()))
514 } else {
515 Poll::Pending
516 }
517 })?);
518 }
519 }
520 }
521 }
522
523 pub async fn read_chunk(&mut self) -> Result<Option<Bytes>> {
525 kio::wait(|waiter| self.poll_read_chunk(waiter)).await
526 }
527
528 pub fn poll_read_all(&mut self, waiter: &kio::Waiter) -> Poll<Result<Bytes>> {
530 match &self.source {
531 Source::Complete(bytes) => {
532 let out = bytes.slice(self.read_idx..);
533 self.read_idx = bytes.len();
534 self.stats.bytes(out.len() as u64);
535 Poll::Ready(Ok(out))
536 }
537 Source::Partial(buf) => {
538 let buf = buf.clone();
539 let size = self.info.size as usize;
540 let read_idx = self.read_idx;
541 ready!(poll_state(&self.state, waiter, |state| {
542 if let Some(err) = &state.abort {
543 return Poll::Ready(Err(err.clone()));
544 }
545 if buf.written(Ordering::Acquire) >= size {
546 Poll::Ready(Ok(()))
547 } else {
548 Poll::Pending
549 }
550 })?);
551 let out = buf.slice(read_idx, size);
552 self.read_idx = size;
553 self.stats.bytes(out.len() as u64);
554 Poll::Ready(Ok(out))
555 }
556 }
557 }
558
559 pub async fn read_all(&mut self) -> Result<Bytes> {
561 kio::wait(|waiter| self.poll_read_all(waiter)).await
562 }
563}
564
565fn poll_state<F, R>(state: &kio::Consumer<GroupState>, waiter: &kio::Waiter, f: F) -> Poll<Result<R>>
568where
569 F: Fn(&kio::Ref<'_, GroupState>) -> Poll<Result<R>>,
570{
571 Poll::Ready(match ready!(state.poll(waiter, f)) {
572 Ok(res) => res,
573 Err(state) => Err(state.abort.clone().unwrap_or(Error::Dropped)),
574 })
575}