Skip to main content

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}