#[repr(C)]
pub struct ForeignBytes {
len: i32,
data: *const u8,
}
impl ForeignBytes {
pub unsafe fn from_raw_parts(data: *const u8, len: i32) -> Self {
Self { len, data }
}
pub fn as_slice(&self) -> &[u8] {
if self.data.is_null() {
assert!(self.len == 0, "null ForeignBytes had non-zero length");
&[]
} else {
unsafe { std::slice::from_raw_parts(self.data, self.len()) }
}
}
pub fn len(&self) -> usize {
self.len
.try_into()
.expect("bytes length negative or overflowed")
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_foreignbytes_access() {
let v = [1u8, 2, 3];
let fbuf = unsafe { ForeignBytes::from_raw_parts(v.as_ptr(), 3) };
assert_eq!(fbuf.len(), 3);
assert_eq!(fbuf.as_slice(), &[1u8, 2, 3]);
}
#[test]
fn test_foreignbytes_empty() {
let v = Vec::<u8>::new();
let fbuf = unsafe { ForeignBytes::from_raw_parts(v.as_ptr(), 0) };
assert_eq!(fbuf.len(), 0);
assert_eq!(fbuf.as_slice(), &[0u8; 0]);
}
#[test]
fn test_foreignbytes_null_means_empty() {
let fbuf = unsafe { ForeignBytes::from_raw_parts(std::ptr::null_mut(), 0) };
assert_eq!(fbuf.as_slice(), &[0u8; 0]);
}
#[test]
#[should_panic]
fn test_foreignbytes_null_must_have_zero_length() {
let fbuf = unsafe { ForeignBytes::from_raw_parts(std::ptr::null_mut(), 12) };
fbuf.as_slice();
}
#[test]
#[should_panic]
fn test_foreignbytes_provided_len_must_be_non_negative() {
let v = [0u8, 1, 2];
let fbuf = unsafe { ForeignBytes::from_raw_parts(v.as_ptr(), -1) };
fbuf.as_slice();
}
}