vmm/io_uring/operation/
cqe.rs

1// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::fmt::Debug;
5
6use crate::io_uring::generated::io_uring_cqe;
7use crate::vstate::memory::ByteValued;
8
9// SAFETY: Struct is POD and contains no references or niches.
10unsafe impl ByteValued for io_uring_cqe {}
11
12/// Wrapper over a completed operation.
13#[derive(Debug)]
14pub struct Cqe<T> {
15    res: i32,
16    user_data: T,
17}
18
19impl<T: Debug> Cqe<T> {
20    /// Construct a Cqe object.
21    pub fn new(res: i32, user_data: T) -> Self {
22        Self { res, user_data }
23    }
24
25    /// Return the number of bytes successfully transferred by this operation.
26    pub fn count(&self) -> u32 {
27        u32::try_from(self.res).unwrap_or(0)
28    }
29
30    /// Return the result associated to the IO operation.
31    pub fn result(&self) -> Result<u32, std::io::Error> {
32        let res = self.res;
33
34        if res < 0 {
35            Err(std::io::Error::from_raw_os_error(res))
36        } else {
37            Ok(u32::try_from(self.res).unwrap())
38        }
39    }
40
41    /// Create a new Cqe, applying the passed function to the user_data.
42    pub fn map_user_data<U: Debug, F: FnOnce(T) -> U>(self, op: F) -> Cqe<U> {
43        Cqe {
44            res: self.res,
45            user_data: op(self.user_data()),
46        }
47    }
48
49    /// Consume the object and return the user_data.
50    pub fn user_data(self) -> T {
51        self.user_data
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    #![allow(clippy::undocumented_unsafe_blocks)]
58    use super::*;
59    #[test]
60    fn test_result() {
61        // Check that `result()` returns an `Error` when `res` is negative.
62        {
63            let user_data = 10_u8;
64            let cqe: Cqe<u8> = Cqe::new(-22, user_data);
65
66            assert_eq!(
67                cqe.result().unwrap_err().kind(),
68                std::io::Error::from_raw_os_error(-22).kind()
69            );
70        }
71
72        // Check that `result()` returns Ok() when `res` is positive.
73        {
74            let user_data = 10_u8;
75            let cqe: Cqe<u8> = Cqe::new(128, user_data);
76
77            assert_eq!(cqe.result().unwrap(), 128);
78        }
79    }
80
81    #[test]
82    fn test_user_data() {
83        let user_data = 10_u8;
84        let cqe: Cqe<u8> = Cqe::new(0, user_data);
85
86        assert_eq!(cqe.user_data(), 10);
87    }
88
89    #[test]
90    fn test_map_user_data() {
91        let user_data = 10_u8;
92        let cqe: Cqe<u8> = Cqe::new(0, user_data);
93        let cqe = cqe.map_user_data(|x| x + 1);
94
95        assert_eq!(cqe.user_data(), 11);
96    }
97}