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