compio_driver/fusion/
op.rs

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));