use std::mem;
use std::ptr;
use std::raw::Slice;
use rawslice::{RawSlice, RawMutSlice};
pub trait RawPtrExt<T> {
fn as_raw_slice(self, len: usize) -> *const [T];
unsafe fn as_slice<'a>(self, len: usize) -> &'a [T];
unsafe fn add(self, count: usize) -> Self;
unsafe fn sub(self, count: usize) -> Self;
unsafe fn read(self) -> T;
unsafe fn copy(self, dest: *mut T, count: usize);
unsafe fn copy_nonoverlapping(self, dest: *mut T, count: usize);
}
pub trait RawMutPtrExt<T> {
fn as_raw_mut_slice(self, len: usize) -> *mut [T];
unsafe fn as_mut_slice<'a>(self, len: usize) -> &'a mut [T];
unsafe fn write(self, src: T);
unsafe fn write_bytes(self, byte: u8, count: usize);
unsafe fn swap(self, y: *mut T);
unsafe fn replace(self, src: T) -> T;
}
impl<T> RawPtrExt<T> for *const T {
fn as_raw_slice(self, len: usize) -> *const [T] {
unsafe {
mem::transmute(Slice {
data: self,
len: len
})
}
}
unsafe fn as_slice<'a>(self, len: usize) -> &'a [T] {
self.as_raw_slice(len).as_slice()
}
unsafe fn read(self) -> T {
ptr::read(self)
}
unsafe fn add(self, count: usize) -> Self {
self.offset(count as isize)
}
unsafe fn sub(self, count: usize) -> Self {
self.offset(-(count as isize))
}
unsafe fn copy(self, dest: *mut T, count: usize) {
ptr::copy(self, dest, count);
}
unsafe fn copy_nonoverlapping(self, dest: *mut T, count: usize) {
ptr::copy_nonoverlapping(self, dest, count);
}
}
impl<T> RawPtrExt<T> for *mut T {
fn as_raw_slice(self, len: usize) -> *const [T] {
(self as *const T).as_raw_slice(len)
}
unsafe fn as_slice<'a>(self, len: usize) -> &'a [T] {
self.as_raw_slice(len).as_slice()
}
unsafe fn read(self) -> T {
ptr::read(self as *const T)
}
unsafe fn add(self, count: usize) -> Self {
self.offset(count as isize)
}
unsafe fn sub(self, count: usize) -> Self {
self.offset(-(count as isize))
}
unsafe fn copy(self, dest: *mut T, count: usize) {
ptr::copy(self, dest, count);
}
unsafe fn copy_nonoverlapping(self, dest: *mut T, count: usize) {
ptr::copy_nonoverlapping(self, dest, count);
}
}
impl<T> RawMutPtrExt<T> for *mut T {
fn as_raw_mut_slice(self, len: usize) -> *mut [T] {
unsafe {
mem::transmute(Slice {
data: self as *const T,
len: len
})
}
}
unsafe fn as_mut_slice<'a>(self, len: usize) -> &'a mut [T] {
self.as_raw_mut_slice(len).as_mut_slice()
}
unsafe fn write(self, src: T) {
ptr::write(self, src);
}
unsafe fn write_bytes(self, byte: u8, count: usize) {
ptr::write_bytes(self, byte, count);
}
unsafe fn swap(self, y: *mut T) {
ptr::swap(self, y);
}
unsafe fn replace(self, src: T) -> T {
ptr::replace(self, src)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_arithmetic() {
unsafe {
let mut x = [1,2,3,4];
let y = x.as_ptr();
assert_eq!(*y, 1);
assert_eq!(*y.add(2), 3);
assert_eq!(*y.add(2).sub(1), 2);
let y = x.as_mut_ptr();
assert_eq!(*y, 1);
assert_eq!(*y.add(2), 3);
assert_eq!(*y.add(2).sub(1), 2);
}
}
#[test]
fn test_read_write() {
unsafe {
let x = &mut 1 as *mut _;
assert_eq!(x.read(), 1);
x.write(2);
assert_eq!(x.read(), 2);
x.write_bytes(0, 1);
assert_eq!(x.read(), 0);
}
}
#[test]
fn test_copy() {
unsafe {
let mut x = [1,2,3,4];
let y = [5,6,7,8];
let xptr = x.as_mut_ptr();
let yptr = y.as_ptr();
xptr.add(1).copy(xptr, 2);
assert_eq!(x, [2,3,3,4]);
yptr.copy_nonoverlapping(xptr, 4);
assert_eq!(x, y);
}
}
#[test]
fn test_swap_replace() {
unsafe {
let x = &mut 1 as *mut _;
let y = &mut 2;
x.swap(y);
assert_eq!(*x, 2);
assert_eq!(*y, 1);
x.replace(3);
assert_eq!(*x, 3);
}
}
}