1use std::{
4 future::{Future, IntoFuture},
5 io::{self},
6 os::fd::AsFd,
7 pin::Pin,
8 task::{Context, Poll, ready},
9};
10
11use compio_driver::{
12 SharedFd, ToSharedFd,
13 op::{Splice as SpliceOp, SpliceFlags},
14};
15use compio_runtime::Submit;
16
17pub fn splice<I: AsFd + 'static, O: AsFd + 'static>(
44 fd_in: &impl ToSharedFd<I>,
45 fd_out: &impl ToSharedFd<O>,
46 len: usize,
47) -> Splice<I, O> {
48 Splice {
49 fd_in: fd_in.to_shared_fd(),
50 fd_out: fd_out.to_shared_fd(),
51 len,
52 offset_in: -1,
53 offset_out: -1,
54 flags: SpliceFlags::empty(),
55 }
56}
57
58pub struct Splice<I, O> {
60 fd_in: SharedFd<I>,
61 fd_out: SharedFd<O>,
62 len: usize,
63 offset_in: i64,
64 offset_out: i64,
65 flags: SpliceFlags,
66}
67
68impl<I, O> Splice<I, O> {
69 pub fn offset_in(mut self, offset: i64) -> Self {
71 self.offset_in = offset;
72 self
73 }
74
75 pub fn offset_out(mut self, offset: i64) -> Self {
77 self.offset_out = offset;
78 self
79 }
80
81 pub fn flags(mut self, flags: u32) -> Self {
83 self.flags = SpliceFlags::from_bits_retain(flags);
84 self
85 }
86}
87
88impl<I: AsFd + 'static, O: AsFd + 'static> IntoFuture for Splice<I, O> {
89 type IntoFuture = SpliceFuture<I, O>;
90 type Output = io::Result<usize>;
91
92 fn into_future(self) -> Self::IntoFuture {
93 let inner = compio_runtime::submit(SpliceOp::new(
94 self.fd_in,
95 self.offset_in,
96 self.fd_out,
97 self.offset_out,
98 self.len,
99 self.flags,
100 ));
101 SpliceFuture { inner }
102 }
103}
104
105pin_project_lite::pin_project! {
106 pub struct SpliceFuture<I, O> where I : AsFd, O: AsFd {
108 #[pin]
109 inner: Submit<SpliceOp<SharedFd<I>, SharedFd<O>>>,
110 }
111}
112
113impl<I: AsFd + 'static, O: AsFd + 'static> Future for SpliceFuture<I, O> {
114 type Output = io::Result<usize>;
115
116 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
117 let res = ready!(self.project().inner.poll(cx));
118 Poll::Ready(res.0)
119 }
120}