use std::fmt;
use std::ops;
use std::slice;
use libc::{c_void, iovec, size_t};
use serde::de::{self, Error};
use serde::{Serialize, Serializer};
use super::utils;
#[derive(Clone)]
pub struct Iovec(iovec);
impl Iovec {
pub(crate) fn from_slice(buf: &[u8]) -> Self {
let iov_len = buf.len();
let iov_base = buf.as_ptr() as *mut c_void;
let iov = iovec { iov_base, iov_len };
iov.into()
}
pub(crate) fn from_slice_mut(buf: &mut [u8]) -> Self {
let iov_len = buf.len();
let iov_base = buf.as_mut_ptr() as *mut c_void;
let iov = iovec { iov_base, iov_len };
iov.into()
}
pub fn as_slice(&self) -> &[u8] {
unsafe { utils::iovec_as_slice(&self.0) }
}
pub fn as_static_slice(&self) -> &'static [u8] {
unsafe { utils::iovec_as_static_slice(self.0) }
}
pub fn as_iovec_mut(&self) -> iovec {
self.0
}
}
impl From<iovec> for Iovec {
#[inline]
fn from(iov: iovec) -> Self {
Self { 0: iov }
}
}
impl From<(*mut c_void, size_t)> for Iovec {
fn from((iov_base, iov_len): (*mut c_void, size_t)) -> Self {
iovec { iov_base, iov_len }.into()
}
}
impl<'a> From<&'a [u8]> for Iovec {
fn from(buf: &[u8]) -> Self {
Self::from_slice(buf)
}
}
impl<'a> From<&'a mut [u8]> for Iovec {
fn from(buf: &mut [u8]) -> Self {
Self::from_slice_mut(buf)
}
}
impl fmt::Debug for Iovec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let iov = self.0;
f.debug_struct("Element::Iovec")
.field("iov_base", &iov.iov_base)
.field("iov_len", &iov.iov_len)
.finish()
}
}
impl PartialEq for Iovec {
fn eq(&self, other: &Self) -> bool {
let (iov1, iov2) = (self.0, other.0);
iov1.iov_base == iov2.iov_base && iov1.iov_len == iov2.iov_len
}
}
impl ops::Deref for Iovec {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
unsafe impl Send for Iovec {}
unsafe impl Sync for Iovec {}
impl Serialize for Iovec {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let iov = self.0;
let buf = unsafe {
let base = iov.iov_base as *const u8;
let len = iov.iov_len as usize;
slice::from_raw_parts(base, len)
};
serializer.serialize_bytes(buf)
}
}
impl<'de> de::Deserialize<'de> for Iovec {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
Err(D::Error::custom("Cannot deserialize Element"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn element_iovec() {
let mut buf = [0x55; 1024];
let iov = buf.as_mut_ptr() as *mut c_void;
let len = buf.len();
let e1 = Iovec::from((iov, len));
let e2 = Iovec::from(buf.as_ref());
assert_eq!(e1, e2);
}
#[test]
fn element_debug() {
let iov = 0x7000_0d48_aef0 as *mut c_void;
let len = 512;
let e = Iovec::from((iov, len));
assert_eq!(
format!("{:?}", e),
"Element::Iovec { iov_base: 0x70000d48aef0, iov_len: 512 }"
);
}
}