compio_driver/sys/fusion/
op.rs1use std::{ffi::CString, hint::unreachable_unchecked};
2
3use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
4use socket2::SockAddr;
5
6use super::*;
7pub use crate::sys::unix_op::*;
8
9macro_rules! op {
10 (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? )) => {
11 ::paste::paste!{
12 enum [< $name Inner >] <$($ty: $trait),*> {
13 Uninit($($arg_t),*),
14 Poll(poll::$name<$($ty),*>),
15 IoUring(iour::$name<$($ty),*>),
16 }
17
18 impl<$($ty: $trait),*> [< $name Inner >]<$($ty),*> {
19 fn poll(&mut self) -> &mut poll::$name<$($ty),*> {
20 match self {
21 Self::Uninit(..) => {
22 unsafe {
23 let Self::Uninit($($arg),*) = std::ptr::read(self) else {
24 unreachable_unchecked()
25 };
26 std::ptr::write(self, Self::Poll(poll::$name::new($($arg),*)));
27 }
28 self.poll()
29 },
30 Self::Poll(op) => op,
31 Self::IoUring(_) => unreachable!("Current driver is not `polling`"),
32 }
33 }
34
35 fn iour(&mut self) -> &mut iour::$name<$($ty),*> {
36 match self {
37 Self::Uninit(..) => {
38 unsafe {
39 let Self::Uninit($($arg),*) = std::ptr::read(self) else {
40 unreachable_unchecked()
41 };
42 std::ptr::write(self, Self::IoUring(iour::$name::new($($arg),*)));
43 }
44 self.iour()
45 },
46 Self::IoUring(op) => op,
47 Self::Poll(_) => unreachable!("Current driver is not `io-uring`"),
48 }
49 }
50 }
51
52 #[doc = concat!("A fused `", stringify!($name), "` operation")]
53 pub struct $name <$($ty: $trait),*> {
54 inner: [< $name Inner >] <$($ty),*>
55 }
56
57 impl<$($ty: $trait),*> IntoInner for $name <$($ty),*> {
58 type Inner = <poll::$name<$($ty),*> as IntoInner>::Inner;
59
60 fn into_inner(mut self) -> Self::Inner {
61 match self.inner {
62 [< $name Inner >]::Uninit(..) => {
63 self.inner.poll();
64 self.into_inner()
65 },
66 [< $name Inner >]::Poll(op) => op.into_inner(),
67 [< $name Inner >]::IoUring(op) => op.into_inner(),
68 }
69 }
70 }
71
72 impl<$($ty: $trait),*> $name <$($ty),*> {
73 #[doc = concat!("Create a new `", stringify!($name), "`.")]
74 pub fn new($($arg: $arg_t),*) -> Self {
75 Self { inner: [< $name Inner >]::Uninit($($arg),*) }
76 }
77 }
78 }
79
80 unsafe impl<$($ty: $trait),*> poll::OpCode for $name<$($ty),*> {
81 fn pre_submit(self: std::pin::Pin<&mut Self>) -> std::io::Result<crate::Decision> {
82 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.pre_submit()
83 }
84
85 fn op_type(self: std::pin::Pin<&mut Self>) -> Option<OpType> {
86 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.op_type()
87 }
88
89 fn operate(
90 self: std::pin::Pin<&mut Self>,
91 ) -> std::task::Poll<std::io::Result<usize>> {
92 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.operate()
93 }
94 }
95
96 unsafe impl<$($ty: $trait),*> iour::OpCode for $name<$($ty),*> {
97 fn create_entry(self: std::pin::Pin<&mut Self>) -> OpEntry {
98 unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry()
99 }
100 }
101 };
102}
103
104#[rustfmt::skip]
105mod iour { pub use crate::sys::iour::{op::*, OpCode}; }
106#[rustfmt::skip]
107mod poll { pub use crate::sys::poll::{op::*, OpCode}; }
108
109op!(<T: IoBufMut, S: AsFd> RecvFrom(fd: S, buffer: T, flags: i32));
110op!(<T: IoBuf, S: AsFd> SendTo(fd: S, buffer: T, addr: SockAddr, flags: i32));
111op!(<T: IoVectoredBufMut, S: AsFd> RecvFromVectored(fd: S, buffer: T, flags: i32));
112op!(<T: IoVectoredBuf, S: AsFd> SendToVectored(fd: S, buffer: T, addr: SockAddr, flags: i32));
113op!(<S: AsFd> FileStat(fd: S));
114op!(<> PathStat(path: CString, follow_symlink: bool));
115
116macro_rules! mop {
117 (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? ) with $pool:ident) => {
118 mop!{ < $($ty: $trait),* > $name ( $( $arg: $arg_t ),* ) with $pool, buffer: crate::BorrowedBuffer<'a> }
119 };
120 (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? ) with $pool:ident, buffer: $buffer:ty) => {
121 ::paste::paste!{
122 enum [< $name Inner >] <$($ty: $trait),*> {
123 Poll(crate::op::managed::$name<$($ty),*>),
124 IoUring(iour::$name<$($ty),*>),
125 }
126
127 impl<$($ty: $trait),*> [< $name Inner >]<$($ty),*> {
128 fn poll(&mut self) -> &mut crate::op::managed::$name<$($ty),*> {
129 match self {
130 Self::Poll(op) => op,
131 Self::IoUring(_) => unreachable!("Current driver is not `io-uring`"),
132 }
133 }
134
135 fn iour(&mut self) -> &mut iour::$name<$($ty),*> {
136 match self {
137 Self::IoUring(op) => op,
138 Self::Poll(_) => unreachable!("Current driver is not `polling`"),
139 }
140 }
141 }
142
143 #[doc = concat!("A fused `", stringify!($name), "` operation")]
144 pub struct $name <$($ty: $trait),*> {
145 inner: [< $name Inner >] <$($ty),*>
146 }
147
148 impl<$($ty: $trait),*> $name <$($ty),*> {
149 #[doc = concat!("Create a new `", stringify!($name), "`.")]
150 pub fn new($($arg: $arg_t),*) -> std::io::Result<Self> {
151 Ok(if $pool.is_io_uring() {
152 Self {
153 inner: [< $name Inner >]::IoUring(iour::$name::new($($arg),*)?),
154 }
155 } else {
156 Self {
157 inner: [< $name Inner >]::Poll(crate::op::managed::$name::new($($arg),*)?),
158 }
159 })
160 }
161 }
162
163 impl<$($ty: $trait),*> crate::TakeBuffer for $name<$($ty),*> {
164 type BufferPool = crate::BufferPool;
165 type Buffer<'a> = $buffer;
166
167 fn take_buffer(
168 self,
169 buffer_pool: &Self::BufferPool,
170 result: io::Result<usize>,
171 buffer_id: u16,
172 ) -> io::Result<Self::Buffer<'_>> {
173 match self.inner {
174 [< $name Inner >]::Poll(inner) => {
175 Ok(inner.take_buffer(buffer_pool, result, buffer_id)?)
176 }
177 [< $name Inner >]::IoUring(inner) => {
178 Ok(inner.take_buffer(buffer_pool, result, buffer_id)?)
179 }
180 }
181 }
182 }
183 }
184
185 unsafe impl<$($ty: $trait),*> poll::OpCode for $name<$($ty),*> {
186 fn pre_submit(self: std::pin::Pin<&mut Self>) -> std::io::Result<crate::Decision> {
187 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.pre_submit()
188 }
189
190 fn op_type(self: std::pin::Pin<&mut Self>) -> Option<OpType> {
191 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.op_type()
192 }
193
194 fn operate(
195 self: std::pin::Pin<&mut Self>,
196 ) -> std::task::Poll<std::io::Result<usize>> {
197 unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.operate()
198 }
199 }
200
201 unsafe impl<$($ty: $trait),*> iour::OpCode for $name<$($ty),*> {
202 fn create_entry(self: std::pin::Pin<&mut Self>) -> OpEntry {
203 unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry()
204 }
205 }
206 };
207}
208
209mop!(<S: AsFd> ReadManagedAt(fd: S, offset: u64, pool: &BufferPool, len: usize) with pool);
210mop!(<S: AsFd> ReadManaged(fd: S, pool: &BufferPool, len: usize) with pool);
211mop!(<S: AsFd> RecvManaged(fd: S, pool: &BufferPool, len: usize, flags: i32) with pool);
212mop!(<S: AsFd> RecvFromManaged(fd: S, pool: &BufferPool, len: usize, flags: i32) with pool, buffer: (crate::BorrowedBuffer<'a>, SockAddr));