use tokio_uring::buf::{BoundedBuf, BoundedBufMut, Slice};
use std::mem;
use std::ops::RangeBounds;
use std::slice::SliceIndex;
#[test]
fn test_vec() {
let mut v = vec![];
assert_eq!(v.as_ptr(), v.stable_ptr());
assert_eq!(v.as_mut_ptr(), v.stable_mut_ptr());
assert_eq!(v.bytes_init(), 0);
assert_eq!(v.bytes_total(), 0);
v.reserve(100);
assert_eq!(v.as_ptr(), v.stable_ptr());
assert_eq!(v.as_mut_ptr(), v.stable_mut_ptr());
assert_eq!(v.bytes_init(), 0);
assert_eq!(v.bytes_total(), v.capacity());
v.extend(b"hello");
assert_eq!(v.as_ptr(), v.stable_ptr());
assert_eq!(v.as_mut_ptr(), v.stable_mut_ptr());
assert_eq!(v.bytes_init(), 5);
assert_eq!(v.bytes_total(), v.capacity());
unsafe {
v.set_init(3);
}
assert_eq!(&v[..], b"hello");
unsafe {
std::ptr::copy(DATA.as_ptr(), v.stable_mut_ptr(), 10);
v.set_init(10);
}
assert_eq!(&v[..], &DATA[..10]);
}
#[test]
fn test_slice() {
let v = &b""[..];
assert_eq!(v.as_ptr(), v.stable_ptr());
assert_eq!(v.bytes_init(), 0);
assert_eq!(v.bytes_total(), 0);
let v = &b"hello"[..];
assert_eq!(v.as_ptr(), v.stable_ptr());
assert_eq!(v.bytes_init(), 5);
assert_eq!(v.bytes_total(), 5);
}
const DATA: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789!?";
macro_rules! test_slice {
(
$( $name:ident => $buf:expr; )*
) => {
$(
mod $name {
use super::*;
#[test]
fn test_slice_read() {
let buf = $buf;
let slice = buf.slice(..);
assert_eq!(slice.begin(), 0);
assert_eq!(slice.end(), DATA.len());
assert_eq!(&slice[..], DATA);
assert_eq!(&slice[5..], &DATA[5..]);
assert_eq!(&slice[10..15], &DATA[10..15]);
assert_eq!(&slice[..15], &DATA[..15]);
let buf = slice.into_inner();
let slice = buf.slice(10..);
assert_eq!(slice.begin(), 10);
assert_eq!(slice.end(), DATA.len());
assert_eq!(&slice[..], &DATA[10..]);
assert_eq!(&slice[10..], &DATA[20..]);
assert_eq!(&slice[5..15], &DATA[15..25]);
assert_eq!(&slice[..15], &DATA[10..25]);
let buf = slice.into_inner();
let slice = buf.slice(5..15);
assert_eq!(slice.begin(), 5);
assert_eq!(slice.end(), 15);
assert_eq!(&slice[..], &DATA[5..15]);
assert_eq!(&slice[5..], &DATA[10..15]);
assert_eq!(&slice[5..8], &DATA[10..13]);
assert_eq!(&slice[..5], &DATA[5..10]);
let buf = slice.into_inner();
let slice = buf.slice(..15);
assert_eq!(slice.begin(), 0);
assert_eq!(slice.end(), 15);
assert_eq!(&slice[..], &DATA[..15]);
assert_eq!(&slice[5..], &DATA[5..15]);
assert_eq!(&slice[5..10], &DATA[5..10]);
assert_eq!(&slice[..5], &DATA[..5]);
}
#[test]
fn test_subslice_read() {
let buf = $buf;
let buf = test_subslice_read_case(buf.slice(..), DATA, ..);
let buf = test_subslice_read_case(buf.slice(..), DATA, 10..);
let buf = test_subslice_read_case(buf.slice(..), DATA, 5..15);
let buf = test_subslice_read_case(buf.slice(..), DATA, ..15);
let buf = test_subslice_read_case(buf.slice(5..), &DATA[5..], ..);
let buf = test_subslice_read_case(buf.slice(5..), &DATA[5..], 5..);
let buf = test_subslice_read_case(buf.slice(5..), &DATA[5..], 5..15);
let buf = test_subslice_read_case(buf.slice(5..), &DATA[5..], ..10);
let buf = test_subslice_read_case(buf.slice(5..25), &DATA[5..25], ..);
let buf = test_subslice_read_case(buf.slice(5..25), &DATA[5..25], 5..);
let buf = test_subslice_read_case(buf.slice(5..25), &DATA[5..25], 5..15);
let buf = test_subslice_read_case(buf.slice(5..25), &DATA[5..25], ..10);
let buf = test_subslice_read_case(buf.slice(..25), &DATA[..25], ..);
let buf = test_subslice_read_case(buf.slice(..25), &DATA[..25], 5..);
let buf = test_subslice_read_case(buf.slice(..25), &DATA[..25], 5..15);
let ___ = test_subslice_read_case(buf.slice(..25), &DATA[..25], ..10);
}
}
)*
};
}
fn test_subslice_read_case<B, R>(slice: Slice<B>, expected: &[u8], range: R) -> B
where
B: tokio_uring::buf::IoBuf,
R: RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> + Clone,
{
use std::ops::{Bound, Index};
let buf_ptr = slice.get_ref().stable_ptr();
let buf_total = slice.get_ref().bytes_total();
let buf_init = slice.get_ref().bytes_init();
let begin = slice.begin();
let end = slice.end();
let subslice = slice.slice(range.clone());
let data = expected.index(range.clone());
match range.start_bound() {
Bound::Included(&n) => {
assert_eq!(subslice.begin(), begin + n);
}
Bound::Excluded(&n) => {
assert_eq!(subslice.begin(), begin + n + 1);
}
Bound::Unbounded => {
assert_eq!(subslice.begin(), begin);
}
}
match range.end_bound() {
Bound::Included(&n) => {
assert_eq!(subslice.end(), begin + n + 1);
}
Bound::Excluded(&n) => {
assert_eq!(subslice.end(), begin + n);
}
Bound::Unbounded => {
assert_eq!(subslice.end(), end);
}
}
assert_eq!(&subslice[..], data);
let buf = subslice.into_inner();
assert_eq!(buf.stable_ptr(), buf_ptr);
assert_eq!(buf.bytes_init(), buf_init);
assert_eq!(buf.bytes_total(), buf_total);
buf
}
test_slice! {
vec => Vec::from(DATA);
slice => DATA;
}
#[test]
fn can_deref_slice_into_uninit_buf() {
let buf = Vec::with_capacity(10).slice(..);
let _ = buf.stable_ptr();
assert_eq!(buf.bytes_init(), 0);
assert_eq!(buf.bytes_total(), 10);
assert!(buf[..].is_empty());
let mut v = Vec::with_capacity(10);
v.push(42);
let mut buf = v.slice(..);
let _ = buf.stable_mut_ptr();
assert_eq!(buf.bytes_init(), 1);
assert_eq!(buf.bytes_total(), 10);
assert_eq!(mem::replace(&mut buf[0], 0), 42);
buf.copy_from_slice(&[43]);
assert_eq!(&buf[..], &[43]);
}