Skip to main content

ntex_io_uring/
opcode2.rs

1use crate::{squeue::Entry, sys, types::sealed};
2
3macro_rules! assign_fd {
4    ( $sqe:ident . sqe . fd = $opfd:expr ) => {
5        match $opfd.into() {
6            sealed::Target::Fd(fd) => $sqe.sqe.fd = fd,
7            sealed::Target::Fixed(idx) => {
8                $sqe.sqe.fd = idx as _;
9                unsafe {
10                    $sqe.sqe.__bindgen_anon_3.msg_flags |=
11                        crate::squeue::Flags::FIXED_FILE.bits() as u32;
12                }
13            }
14        }
15    };
16    ( $sqe:ident . 0 . fd = $opfd:expr ) => {
17        match $opfd.into() {
18            sealed::Target::Fd(fd) => $sqe.0.fd = fd,
19            sealed::Target::Fixed(idx) => {
20                $sqe.0.fd = idx as _;
21                $sqe.0.__bindgen_anon_3.msg_flags = crate::squeue::Flags::FIXED_FILE.bits() as u32;
22            }
23        }
24    };
25}
26
27macro_rules! opcode {
28    ($( #[$outer:meta] )*
29     $name:ident, $opcode:expr) => {
30        $( #[$outer] )*
31        pub struct $name<'a> {
32            sqe: &'a mut sys::io_uring_sqe,
33        }
34
35        impl<'a> $name<'a> {
36            pub const CODE: u8 = $opcode as u8;
37
38            pub fn new(entry: &'a mut Entry) -> Self {
39                entry.0.opcode = Self::CODE;
40                Self { sqe: &mut entry.0 }
41            }
42
43            pub fn with(entry: &'a mut Entry, fd: impl sealed::UseFixed) -> Self {
44                entry.0.opcode = Self::CODE;
45                assign_fd!(entry.0.fd = fd);
46
47                Self { sqe: &mut entry.0 }
48            }
49
50            #[doc(hidden)]
51            pub fn fd(self, fd: impl sealed::UseFixed) -> Self {
52                assign_fd!(self.sqe.fd = fd);
53                self
54            }
55
56            pub fn ioprio(self, ioprio: u16) -> Self {
57                self.sqe.ioprio = ioprio;
58                self
59            }
60
61            pub fn flags(self, flags: i32) -> Self {
62                unsafe {
63                    self.sqe.__bindgen_anon_3.msg_flags |= flags as u32;
64                }
65                self
66            }
67        }
68    };
69}
70
71macro_rules! opcode_buf {
72    () => {
73        pub fn buffer(self, buf: *mut u8, len: u32) -> Self {
74            self.sqe.__bindgen_anon_2.addr = buf as _;
75            self.sqe.len = len;
76            self
77        }
78
79        #[doc(hidden)]
80        pub fn buf(self, buf: *mut u8) -> Self {
81            self.sqe.__bindgen_anon_2.addr = buf as _;
82            self
83        }
84
85        #[doc(hidden)]
86        pub fn len(self, len: u32) -> Self {
87            self.sqe.len = len;
88            self
89        }
90    };
91}
92
93macro_rules! opcode_send_buf {
94    () => {
95        pub fn buffer(self, buf: *const u8, len: u32) -> Self {
96            self.sqe.__bindgen_anon_2.addr = buf as _;
97            self.sqe.len = len;
98            self
99        }
100
101        #[doc(hidden)]
102        pub fn buf(self, buf: *const u8) -> Self {
103            self.sqe.__bindgen_anon_2.addr = buf as _;
104            self
105        }
106
107        #[doc(hidden)]
108        pub fn len(self, len: u32) -> Self {
109            self.sqe.len = len;
110            self
111        }
112    };
113}
114
115opcode! {
116    /// Send a message on a socket, equivalent to `send(2)`.
117    Send, sys::IORING_OP_SEND
118}
119
120impl<'a> Send<'a> {
121    opcode_send_buf!();
122
123    /// Set the destination address, for sending from an unconnected socket.
124    ///
125    /// When set, `dest_addr_len` must be set as well.
126    /// See also `man 3 io_uring_prep_send_set_addr`.
127    pub fn dest_addr(self, addr: *const libc::sockaddr, len: libc::socklen_t) -> Self {
128        self.sqe.__bindgen_anon_1.addr2 = addr as _;
129        self.sqe.__bindgen_anon_5.__bindgen_anon_1.addr_len = len as _;
130        self
131    }
132}
133
134opcode! {
135    /// Receive a message from a socket, equivalent to `recv(2)`.
136    Recv, sys::IORING_OP_RECV
137}
138
139impl<'a> Recv<'a> {
140    opcode_buf!();
141
142    pub fn buf_group(self, grp: u16) -> Self {
143        self.sqe.__bindgen_anon_4.buf_group = grp;
144        self
145    }
146}
147
148// === 6.0 ===
149
150opcode! {
151    /// Send a zerocopy message on a socket, equivalent to `send(2)`.
152    ///
153    /// When `dest_addr` is non-zero it points to the address of the target with `dest_addr_len`
154    /// specifying its size, turning the request into a `sendto(2)`
155    ///
156    /// A fixed (pre-mapped) buffer can optionally be used from pre-mapped buffers that have been
157    /// previously registered with [`Submitter::register_buffers`](crate::Submitter::register_buffers).
158    ///
159    /// This operation might result in two completion queue entries.
160    /// See the `IORING_OP_SEND_ZC` section at [io_uring_enter][] for the exact semantics.
161    /// Notifications posted by this operation can be checked with [notif](crate::cqueue::notif).
162    ///
163    /// [io_uring_enter]: https://man7.org/linux/man-pages/man2/io_uring_enter.2.html
164    SendZc, sys::IORING_OP_SEND_ZC
165}
166
167impl<'a> SendZc<'a> {
168    opcode_send_buf!();
169
170    /// The `buf_index` is an index into an array of fixed buffers, and is only valid if fixed
171    /// buffers were registered.
172    ///
173    /// The buf and len arguments must fall within a region specified by buf_index in the
174    /// previously registered buffer. The buffer need not be aligned with the start of the
175    /// registered buffer.
176    pub fn buf_index(self, idx: u16) -> Self {
177        self.sqe.__bindgen_anon_4.buf_index = idx;
178        self.sqe.ioprio |= sys::IORING_RECVSEND_FIXED_BUF as u16;
179        self
180    }
181
182    /// Set the destination address, for sending from an unconnected socket.
183    ///
184    /// When set, `dest_addr_len` must be set as well.
185    /// See also `man 3 io_uring_prep_send_set_addr`.
186    pub fn dest_addr(self, addr: *const libc::sockaddr, len: libc::socklen_t) -> Self {
187        self.sqe.__bindgen_anon_1.addr2 = addr as _;
188        self.sqe.__bindgen_anon_5.__bindgen_anon_1.addr_len = len as _;
189        self
190    }
191}