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()); // Assume init does not go backwards unsafe { v.set_init(3); } assert_eq!(&v[..], b"hello"); // Initializing goes forward 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(slice: Slice, expected: &[u8], range: R) -> B where B: tokio_uring::buf::IoBuf, R: RangeBounds + 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]); }