rexsgdata/
iovec.rs

1//
2// Copyright (c) 2019 RepliXio Ltd. All rights reserved.
3// Use is subject to license terms.
4//
5
6use std::fmt;
7use std::ops;
8use std::slice;
9
10use libc::{c_void, iovec, size_t};
11use serde::de::{self, Error};
12use serde::{Serialize, Serializer};
13
14use super::utils;
15
16/// Intermediate element that can represent either regular `iovec` or a sequence of zeroes
17#[derive(Clone)]
18pub struct Iovec(iovec);
19
20impl Iovec {
21    pub(crate) fn from_slice(buf: &[u8]) -> Self {
22        let iov_len = buf.len();
23        let iov_base = buf.as_ptr() as *mut c_void;
24        let iov = iovec { iov_base, iov_len };
25        iov.into()
26    }
27
28    pub(crate) fn from_slice_mut(buf: &mut [u8]) -> Self {
29        let iov_len = buf.len();
30        let iov_base = buf.as_mut_ptr() as *mut c_void;
31        let iov = iovec { iov_base, iov_len };
32        iov.into()
33    }
34
35    /// Get a view of an `Element` as a vector of slices
36    pub fn as_slice(&self) -> &[u8] {
37        unsafe { utils::iovec_as_slice(&self.0) }
38    }
39
40    pub fn as_static_slice(&self) -> &'static [u8] {
41        unsafe { utils::iovec_as_static_slice(self.0) }
42    }
43
44    pub fn as_iovec_mut(&self) -> iovec {
45        self.0
46    }
47}
48
49impl From<iovec> for Iovec {
50    #[inline]
51    fn from(iov: iovec) -> Self {
52        Self { 0: iov }
53    }
54}
55
56impl From<(*mut c_void, size_t)> for Iovec {
57    fn from((iov_base, iov_len): (*mut c_void, size_t)) -> Self {
58        iovec { iov_base, iov_len }.into()
59    }
60}
61
62impl<'a> From<&'a [u8]> for Iovec {
63    fn from(buf: &[u8]) -> Self {
64        Self::from_slice(buf)
65    }
66}
67
68impl<'a> From<&'a mut [u8]> for Iovec {
69    fn from(buf: &mut [u8]) -> Self {
70        Self::from_slice_mut(buf)
71    }
72}
73
74impl fmt::Debug for Iovec {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        let iov = self.0;
77        f.debug_struct("Element::Iovec")
78            .field("iov_base", &iov.iov_base)
79            .field("iov_len", &iov.iov_len)
80            .finish()
81    }
82}
83
84impl PartialEq for Iovec {
85    fn eq(&self, other: &Self) -> bool {
86        let (iov1, iov2) = (self.0, other.0);
87        iov1.iov_base == iov2.iov_base && iov1.iov_len == iov2.iov_len
88    }
89}
90
91impl ops::Deref for Iovec {
92    type Target = [u8];
93
94    fn deref(&self) -> &Self::Target {
95        self.as_slice()
96    }
97}
98
99unsafe impl Send for Iovec {}
100unsafe impl Sync for Iovec {}
101
102impl Serialize for Iovec {
103    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104    where
105        S: Serializer,
106    {
107        let iov = self.0;
108        let buf = unsafe {
109            let base = iov.iov_base as *const u8;
110            let len = iov.iov_len as usize;
111            slice::from_raw_parts(base, len)
112        };
113        serializer.serialize_bytes(buf)
114    }
115}
116
117impl<'de> de::Deserialize<'de> for Iovec {
118    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
119    where
120        D: de::Deserializer<'de>,
121    {
122        Err(D::Error::custom("Cannot deserialize Element"))
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129
130    #[test]
131    fn element_iovec() {
132        let mut buf = [0x55; 1024];
133        let iov = buf.as_mut_ptr() as *mut c_void;
134        let len = buf.len();
135        let e1 = Iovec::from((iov, len));
136        let e2 = Iovec::from(buf.as_ref());
137        assert_eq!(e1, e2);
138    }
139
140    #[test]
141    fn element_debug() {
142        let iov = 0x7000_0d48_aef0 as *mut c_void;
143        let len = 512;
144        let e = Iovec::from((iov, len));
145        assert_eq!(
146            format!("{:?}", e),
147            "Element::Iovec { iov_base: 0x70000d48aef0, iov_len: 512 }"
148        );
149    }
150}