compio_driver/sys/extra.rs
1use std::{fmt::Debug, io};
2
3use super::*;
4
5/// Platform-specific extra data associated with a driver instance.
6///
7/// It can be used to set options for or get extra data from I/O operations.
8#[repr(transparent)]
9pub struct Extra(pub(super) imp::Extra);
10
11impl Debug for Extra {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 f.debug_struct("Extra").field("sys", &"<...>").finish()
14 }
15}
16
17impl<I: Into<imp::Extra>> From<I> for Extra {
18 fn from(inner: I) -> Self {
19 Self::new(inner.into())
20 }
21}
22
23impl Extra {
24 pub(super) fn new(inner: imp::Extra) -> Self {
25 Self(inner)
26 }
27
28 /// Set the personality, returning the modified Extra.
29 ///
30 /// This is a no-op when not using `io_uring` driver.
31 pub fn with_personality(mut self, personality: u16) -> Self {
32 self.set_personality(personality);
33 self
34 }
35
36 /// Set the personality for this operation.
37 ///
38 /// This is a no-op when not using `io_uring` driver.
39 pub fn set_personality(&mut self, personality: u16) {
40 #[cfg(io_uring)]
41 if let Some(extra) = self.try_as_iour_mut() {
42 extra.set_personality(personality);
43 }
44 #[cfg(not(io_uring))]
45 let _ = personality;
46 }
47
48 /// Get the personality for this operation.
49 ///
50 /// If the personality was not set with [`set_personality`] or the platform
51 /// does not support it, returns [`None`].
52 ///
53 /// [`set_personality`]: Extra::set_personality
54 pub fn get_personality(&self) -> Option<u16> {
55 #[cfg(io_uring)]
56 if let Some(extra) = self.try_as_iour() {
57 extra.get_personality()
58 } else {
59 None
60 }
61 #[cfg(not(io_uring))]
62 None
63 }
64
65 /// Try to get the buffer ID associated with this operation.
66 ///
67 /// # Behavior
68 ///
69 /// This is only supported on `io_uring` drivers, in which the driver will
70 /// try to extract `buffer_id` returned by the kernel as a part of `flags`.
71 /// If the id cannot be extracted from the flag, an [`InvalidInput`]
72 /// [`io::Error`] will be returned. On other platforms, this will always
73 /// return `Ok(0)`.
74 ///
75 /// [`InvalidInput`]: io::ErrorKind::InvalidInput
76 pub fn buffer_id(&self) -> io::Result<u16> {
77 #[cfg(io_uring)]
78 {
79 if let Some(extra) = self.try_as_iour() {
80 extra
81 .buffer_id()
82 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "flags are invalid"))
83 } else {
84 Ok(0)
85 }
86 }
87 #[cfg(not(io_uring))]
88 {
89 // On other platforms, buffer IDs are not supported nor used, so it's okay to
90 // return `Ok(0)`.
91 Ok(0)
92 }
93 }
94}