1use std::sync::Arc;
2use std::sync::atomic::{AtomicUsize, Ordering};
3use std::task::{Poll, ready};
4
5use bytes::buf::UninitSlice;
6use bytes::{BufMut, Bytes};
7
8use crate::{Error, Result};
9
10pub(crate) const MAX_FRAME_SIZE: u64 = 32 * 1024 * 1024;
26
27#[derive(Clone, Debug)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33pub struct Frame {
34 pub size: u64,
36}
37
38impl Frame {
39 pub fn produce(self) -> FrameProducer {
41 FrameProducer::new(self)
42 }
43}
44
45impl From<usize> for Frame {
46 fn from(size: usize) -> Self {
47 Self { size: size as u64 }
48 }
49}
50
51impl From<u64> for Frame {
52 fn from(size: u64) -> Self {
53 Self { size }
54 }
55}
56
57impl From<u32> for Frame {
58 fn from(size: u32) -> Self {
59 Self { size: size as u64 }
60 }
61}
62
63impl From<u16> for Frame {
64 fn from(size: u16) -> Self {
65 Self { size: size as u64 }
66 }
67}
68
69#[derive(Clone)]
79struct FrameBuf(Arc<FrameBufInner>);
80
81struct FrameBufInner {
82 data: *mut u8,
84 capacity: usize,
85 written: AtomicUsize,
86}
87
88unsafe impl Send for FrameBufInner {}
92unsafe impl Sync for FrameBufInner {}
93
94impl Drop for FrameBufInner {
95 fn drop(&mut self) {
96 unsafe {
99 let slice = std::ptr::slice_from_raw_parts_mut(self.data, self.capacity);
100 drop(Box::from_raw(slice));
101 }
102 }
103}
104
105impl FrameBuf {
106 fn new(size: usize) -> Self {
107 let boxed: Box<[u8]> = vec![0u8; size].into_boxed_slice();
108 let capacity = boxed.len();
109 let data = Box::into_raw(boxed) as *mut u8;
110 Self(Arc::new(FrameBufInner {
111 data,
112 capacity,
113 written: AtomicUsize::new(0),
114 }))
115 }
116
117 fn capacity(&self) -> usize {
118 self.0.capacity
119 }
120
121 fn written(&self, ord: Ordering) -> usize {
122 self.0.written.load(ord)
123 }
124
125 unsafe fn data_ptr(&self) -> *mut u8 {
127 self.0.data
128 }
129
130 unsafe fn store_written(&self, new_written: usize) {
132 self.0.written.store(new_written, Ordering::Release);
134 }
135}
136
137impl AsRef<[u8]> for FrameBuf {
138 fn as_ref(&self) -> &[u8] {
139 let written = self.0.written.load(Ordering::Acquire);
142 unsafe { std::slice::from_raw_parts(self.0.data, written) }
146 }
147}
148
149#[derive(Default, Debug)]
150struct FrameState {
151 fin: bool,
153 abort: Option<Error>,
155}
156
157pub struct FrameProducer {
165 info: Frame,
166 state: kio::Producer<FrameState>,
167 buf: FrameBuf,
168}
169
170impl std::ops::Deref for FrameProducer {
171 type Target = Frame;
172
173 fn deref(&self) -> &Self::Target {
174 &self.info
175 }
176}
177
178impl FrameProducer {
179 pub fn new(info: Frame) -> Self {
181 let buf = FrameBuf::new(info.size as usize);
182 Self {
183 info,
184 state: kio::Producer::new(FrameState::default()),
185 buf,
186 }
187 }
188
189 pub fn write<B: Into<Bytes>>(&mut self, chunk: B) -> Result<()> {
193 let chunk = chunk.into();
194 if chunk.len() > self.remaining_mut() {
195 return Err(Error::WrongSize);
196 }
197 self.bail_if_aborted()?;
199 self.put_slice(&chunk);
200 Ok(())
201 }
202
203 pub fn finish(&mut self) -> Result<()> {
207 let written = self.buf.written(Ordering::Acquire);
208 if written != self.buf.capacity() {
209 return Err(Error::WrongSize);
210 }
211 let mut state = self.modify()?;
213 state.fin = true;
214 Ok(())
215 }
216
217 pub fn abort(&mut self, err: Error) -> Result<()> {
219 let mut guard = self.modify()?;
220 guard.abort = Some(err);
221 guard.close();
222 Ok(())
223 }
224
225 pub fn consume(&self) -> FrameConsumer {
227 FrameConsumer {
228 info: self.info.clone(),
229 state: self.state.consume(),
230 buf: self.buf.clone(),
231 read_idx: 0,
232 }
233 }
234
235 pub(crate) fn poll_read_all(&self, waiter: &kio::Waiter) -> Poll<Result<Bytes>> {
243 let res = ready!(self.state.poll_ref(waiter, |state| {
244 if state.fin {
245 Poll::Ready(Ok(()))
246 } else if let Some(err) = &state.abort {
247 Poll::Ready(Err(err.clone()))
248 } else {
249 Poll::Pending
250 }
251 }));
252
253 match res {
254 Ok(Ok(())) => {
255 let written = self.buf.written(Ordering::Acquire);
257 Poll::Ready(Ok(Bytes::from_owner(self.buf.clone()).slice(0..written)))
258 }
259 Ok(Err(err)) => Poll::Ready(Err(err)),
260 Err(state) => Poll::Ready(Err(state.abort.clone().unwrap_or(Error::Dropped))),
261 }
262 }
263
264 pub async fn unused(&self) -> Result<()> {
266 self.state
267 .unused()
268 .await
269 .map_err(|r| r.abort.clone().unwrap_or(Error::Dropped))
270 }
271
272 fn modify(&mut self) -> Result<kio::Mut<'_, FrameState>> {
273 self.state
274 .write()
275 .map_err(|r| r.abort.clone().unwrap_or(Error::Dropped))
276 }
277
278 fn bail_if_aborted(&self) -> Result<()> {
279 let state = self.state.read();
280 if let Some(err) = &state.abort {
281 return Err(err.clone());
282 }
283 Ok(())
284 }
285}
286
287unsafe impl BufMut for FrameProducer {
294 fn remaining_mut(&self) -> usize {
295 self.buf.capacity() - self.buf.written(Ordering::Acquire)
296 }
297
298 fn chunk_mut(&mut self) -> &mut UninitSlice {
299 let written = self.buf.written(Ordering::Acquire);
300 let cap = self.buf.capacity();
301 unsafe {
305 let ptr = self.buf.data_ptr().add(written);
306 UninitSlice::from_raw_parts_mut(ptr, cap - written)
307 }
308 }
309
310 unsafe fn advance_mut(&mut self, cnt: usize) {
311 let cap = self.buf.capacity();
312 let prev = self.buf.written(Ordering::Relaxed);
313 assert!(
314 prev + cnt <= cap,
315 "advance_mut past frame.size: prev={prev} cnt={cnt} cap={cap}"
316 );
317 unsafe { self.buf.store_written(prev + cnt) };
319
320 if let Ok(mut state) = self.state.write() {
323 if prev + cnt == cap {
324 state.fin = true;
325 }
326 }
327 }
328}
329
330impl Clone for FrameProducer {
331 fn clone(&self) -> Self {
332 Self {
333 info: self.info.clone(),
334 state: self.state.clone(),
335 buf: self.buf.clone(),
336 }
337 }
338}
339
340impl From<Frame> for FrameProducer {
341 fn from(info: Frame) -> Self {
342 FrameProducer::new(info)
343 }
344}
345
346#[derive(Clone)]
348pub struct FrameConsumer {
349 info: Frame,
350 state: kio::Consumer<FrameState>,
351 buf: FrameBuf,
352 read_idx: usize,
355}
356
357impl std::ops::Deref for FrameConsumer {
358 type Target = Frame;
359
360 fn deref(&self) -> &Self::Target {
361 &self.info
362 }
363}
364
365impl FrameConsumer {
366 fn poll<F, R>(&self, waiter: &kio::Waiter, f: F) -> Poll<Result<R>>
368 where
369 F: Fn(&kio::Ref<'_, FrameState>) -> Poll<Result<R>>,
370 {
371 Poll::Ready(match ready!(self.state.poll(waiter, f)) {
372 Ok(res) => res,
373 Err(state) => Err(state.abort.clone().unwrap_or(Error::Dropped)),
374 })
375 }
376
377 fn snapshot(&self, read_idx: usize) -> Option<Bytes> {
378 let written = self.buf.written(Ordering::Acquire);
381 if written > read_idx {
382 Some(Bytes::from_owner(self.buf.clone()).slice(read_idx..written))
383 } else {
384 None
385 }
386 }
387
388 pub fn poll_read_all(&mut self, waiter: &kio::Waiter) -> Poll<Result<Bytes>> {
393 let read_idx = self.read_idx;
394 let res = ready!(self.poll(waiter, |state| {
395 if state.fin {
396 return Poll::Ready(Ok(()));
397 }
398 if let Some(err) = &state.abort {
399 return Poll::Ready(Err(err.clone()));
400 }
401 Poll::Pending
402 }));
403 match res {
404 Ok(()) => {
405 let bytes = self
407 .snapshot(read_idx)
408 .unwrap_or_else(|| Bytes::from_owner(self.buf.clone()).slice(read_idx..read_idx));
409 self.read_idx = self.buf.capacity();
410 Poll::Ready(Ok(bytes))
411 }
412 Err(e) => Poll::Ready(Err(e)),
413 }
414 }
415
416 pub async fn read_all(&mut self) -> Result<Bytes> {
418 kio::wait(|waiter| self.poll_read_all(waiter)).await
419 }
420
421 pub fn poll_read_all_chunks(&mut self, waiter: &kio::Waiter) -> Poll<Result<Vec<Bytes>>> {
424 let bytes = ready!(self.poll_read_all(waiter)?);
425 Poll::Ready(Ok(if bytes.is_empty() { Vec::new() } else { vec![bytes] }))
426 }
427
428 pub fn poll_read_chunk(&mut self, waiter: &kio::Waiter) -> Poll<Result<Option<Bytes>>> {
434 let read_idx = self.read_idx;
435 let res = ready!(self.poll(waiter, |state| {
436 let written = self.buf.written(Ordering::Acquire);
437 if written > read_idx {
438 return Poll::Ready(Ok(Some(written)));
439 }
440 if state.fin {
441 return Poll::Ready(Ok(None));
442 }
443 if let Some(err) = &state.abort {
444 return Poll::Ready(Err(err.clone()));
445 }
446 Poll::Pending
447 }));
448 match res {
449 Ok(Some(written)) => {
450 let bytes = Bytes::from_owner(self.buf.clone()).slice(read_idx..written);
451 self.read_idx = written;
452 Poll::Ready(Ok(Some(bytes)))
453 }
454 Ok(None) => Poll::Ready(Ok(None)),
455 Err(e) => Poll::Ready(Err(e)),
456 }
457 }
458
459 pub async fn read_chunk(&mut self) -> Result<Option<Bytes>> {
461 kio::wait(|waiter| self.poll_read_chunk(waiter)).await
462 }
463
464 pub fn poll_read_chunks(&mut self, waiter: &kio::Waiter) -> Poll<Result<Vec<Bytes>>> {
467 match ready!(self.poll_read_chunk(waiter)?) {
468 Some(b) => Poll::Ready(Ok(vec![b])),
469 None => Poll::Ready(Ok(Vec::new())),
470 }
471 }
472
473 pub async fn read_chunks(&mut self) -> Result<Vec<Bytes>> {
475 kio::wait(|waiter| self.poll_read_chunks(waiter)).await
476 }
477}
478
479#[cfg(test)]
480mod test {
481 use super::*;
482 use futures::FutureExt;
483
484 #[test]
485 fn single_chunk_roundtrip() {
486 let mut producer = Frame { size: 5 }.produce();
487 producer.write(Bytes::from_static(b"hello")).unwrap();
488 producer.finish().unwrap();
489
490 let mut consumer = producer.consume();
491 let data = consumer.read_all().now_or_never().unwrap().unwrap();
492 assert_eq!(data, Bytes::from_static(b"hello"));
493 }
494
495 #[test]
496 fn multi_chunk_read_all() {
497 let mut producer = Frame { size: 10 }.produce();
498 producer.write(Bytes::from_static(b"hello")).unwrap();
499 producer.write(Bytes::from_static(b"world")).unwrap();
500 producer.finish().unwrap();
501
502 let mut consumer = producer.consume();
503 let data = consumer.read_all().now_or_never().unwrap().unwrap();
504 assert_eq!(data, Bytes::from_static(b"helloworld"));
505 }
506
507 #[test]
508 fn read_chunk_sequential() {
509 let mut producer = Frame { size: 10 }.produce();
510 producer.write(Bytes::from_static(b"hello")).unwrap();
511 let mut consumer = producer.consume();
514 let c1 = consumer.read_chunk().now_or_never().unwrap().unwrap();
515 assert_eq!(c1, Some(Bytes::from_static(b"hello")));
516
517 producer.write(Bytes::from_static(b"world")).unwrap();
518 producer.finish().unwrap();
519
520 let c2 = consumer.read_chunk().now_or_never().unwrap().unwrap();
521 assert_eq!(c2, Some(Bytes::from_static(b"world")));
522 let c3 = consumer.read_chunk().now_or_never().unwrap().unwrap();
523 assert_eq!(c3, None);
524 }
525
526 #[test]
527 fn read_all_chunks() {
528 let mut producer = Frame { size: 10 }.produce();
529 producer.write(Bytes::from_static(b"hello")).unwrap();
530 producer.write(Bytes::from_static(b"world")).unwrap();
531 producer.finish().unwrap();
532
533 let mut consumer = producer.consume();
534 let chunks = consumer.read_chunks().now_or_never().unwrap().unwrap();
535 assert_eq!(chunks.len(), 1);
536 assert_eq!(chunks[0], Bytes::from_static(b"helloworld"));
537 }
538
539 #[test]
540 fn finish_checks_remaining() {
541 let mut producer = Frame { size: 5 }.produce();
542 producer.write(Bytes::from_static(b"hi")).unwrap();
543 let err = producer.finish().unwrap_err();
544 assert!(matches!(err, Error::WrongSize));
545 }
546
547 #[test]
548 fn write_too_many_bytes() {
549 let mut producer = Frame { size: 3 }.produce();
550 let err = producer.write(Bytes::from_static(b"toolong")).unwrap_err();
551 assert!(matches!(err, Error::WrongSize));
552 }
553
554 #[test]
555 fn abort_propagates() {
556 let mut producer = Frame { size: 5 }.produce();
557 let mut consumer = producer.consume();
558 producer.abort(Error::Cancel).unwrap();
559
560 let err = consumer.read_all().now_or_never().unwrap().unwrap_err();
561 assert!(matches!(err, Error::Cancel));
562 }
563
564 #[test]
565 fn empty_frame() {
566 let mut producer = Frame { size: 0 }.produce();
567 producer.finish().unwrap();
568
569 let mut consumer = producer.consume();
570 let data = consumer.read_all().now_or_never().unwrap().unwrap();
571 assert_eq!(data, Bytes::new());
572 }
573
574 #[tokio::test]
575 async fn pending_then_ready() {
576 let mut producer = Frame { size: 5 }.produce();
577 let mut consumer = producer.consume();
578
579 assert!(consumer.read_all().now_or_never().is_none());
581
582 producer.write(Bytes::from_static(b"hello")).unwrap();
583 producer.finish().unwrap();
584
585 let data = consumer.read_all().now_or_never().unwrap().unwrap();
586 assert_eq!(data, Bytes::from_static(b"hello"));
587 }
588
589 #[test]
590 fn buf_mut_roundtrip() {
591 let mut producer = Frame { size: 12 }.produce();
593 assert_eq!(producer.remaining_mut(), 12);
594 producer.put_slice(b"hello");
595 assert_eq!(producer.remaining_mut(), 7);
596 producer.put_slice(b" world!");
597 assert_eq!(producer.remaining_mut(), 0);
598 producer.finish().unwrap();
599
600 let mut consumer = producer.consume();
601 let data = consumer.read_all().now_or_never().unwrap().unwrap();
602 assert_eq!(data, Bytes::from_static(b"hello world!"));
603 }
604
605 #[test]
606 #[should_panic(expected = "advance_mut past frame.size")]
607 fn buf_mut_advance_past_capacity_panics() {
608 let mut producer = Frame { size: 4 }.produce();
609 unsafe { producer.advance_mut(5) };
611 }
612
613 #[test]
614 fn read_chunk_streams_partial_writes() {
615 let mut producer = Frame { size: 6 }.produce();
616 let mut consumer = producer.consume();
617
618 producer.write(Bytes::from_static(b"foo")).unwrap();
619 let c1 = consumer.read_chunk().now_or_never().unwrap().unwrap();
620 assert_eq!(c1, Some(Bytes::from_static(b"foo")));
621
622 assert!(consumer.read_chunk().now_or_never().is_none());
624
625 producer.write(Bytes::from_static(b"bar")).unwrap();
626 producer.finish().unwrap();
627 let c2 = consumer.read_chunk().now_or_never().unwrap().unwrap();
628 assert_eq!(c2, Some(Bytes::from_static(b"bar")));
629 let c3 = consumer.read_chunk().now_or_never().unwrap().unwrap();
630 assert_eq!(c3, None);
631 }
632
633 #[test]
634 fn cloned_consumer_independent_cursor() {
635 let mut producer = Frame { size: 10 }.produce();
636 let mut c1 = producer.consume();
637 producer.write(Bytes::from_static(b"hello")).unwrap();
638
639 let chunk = c1.read_chunk().now_or_never().unwrap().unwrap();
641 assert_eq!(chunk, Some(Bytes::from_static(b"hello")));
642 let mut c2 = c1.clone();
643
644 producer.write(Bytes::from_static(b"world")).unwrap();
645 producer.finish().unwrap();
646
647 let chunk = c1.read_chunk().now_or_never().unwrap().unwrap();
649 assert_eq!(chunk, Some(Bytes::from_static(b"world")));
650 let chunk = c2.read_chunk().now_or_never().unwrap().unwrap();
651 assert_eq!(chunk, Some(Bytes::from_static(b"world")));
652 }
653}