Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions libcc2rs/src/fn_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::marker::PhantomData;
use std::ops::Deref;
use std::rc::Rc;

use crate::rc::{AnyPtr, ErasedPtr};
use crate::rc::{AnyPtr, ErasedPtr, Ptr};
use crate::reinterpret::ByteRepr;

pub trait FnAddr {
Expand Down Expand Up @@ -146,20 +146,14 @@ impl<T> Eq for FnPtr<T> {}
impl<T: 'static> ByteRepr for FnPtr<T> {}

impl<T: 'static> ErasedPtr for FnPtr<T> {
fn pointee_type_id(&self) -> TypeId {
TypeId::of::<T>()
}
fn memcpy(&self, _src: &dyn ErasedPtr, _len: usize) {
panic!("memcpy not supported on fn pointer");
fn as_bytes(&self) -> Ptr<u8> {
panic!("byte view not supported on fn pointer");
}
fn as_any(&self) -> &dyn Any {
self
}
fn equals(&self, other: &dyn ErasedPtr) -> Option<bool> {
if self.pointee_type_id() != other.pointee_type_id() {
return None;
}
other.as_any().downcast_ref::<FnPtr<T>>().map(|o| self == o)
fn equals(&self, other: &dyn ErasedPtr) -> bool {
other.as_any().downcast_ref::<FnPtr<T>>() == Some(self)
}
fn is_null(&self) -> bool {
FnPtr::is_null(self)
Expand Down
90 changes: 18 additions & 72 deletions libcc2rs/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,49 +1042,33 @@ impl Ptr<u8> {
}

pub(crate) trait ErasedPtr: std::any::Any {
fn pointee_type_id(&self) -> std::any::TypeId;
fn memcpy(&self, src: &dyn ErasedPtr, len: usize);
fn as_bytes(&self) -> Ptr<u8>;
fn as_any(&self) -> &dyn std::any::Any;
fn equals(&self, other: &dyn ErasedPtr) -> Option<bool>;
fn equals(&self, other: &dyn ErasedPtr) -> bool;
fn is_null(&self) -> bool;
}

impl PartialEq for dyn ErasedPtr {
fn eq(&self, other: &Self) -> bool {
self.equals(other)
}
}

impl<T> ErasedPtr for Ptr<T>
where
T: ByteRepr + 'static,
Ptr<T>: PartialEq,
{
fn pointee_type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<T>()
}

fn memcpy(&self, src: &dyn ErasedPtr, len: usize) {
if self.pointee_type_id() != src.pointee_type_id() {
panic!("memcpy: type mismatch");
}
let src_ptr = src
.as_any()
.downcast_ref::<Ptr<T>>()
.expect("memcpy: downcast to Ptr<T> failed");
let dst_bytes: Ptr<u8> = self.reinterpret_cast();
let src_bytes: Ptr<u8> = src_ptr.reinterpret_cast();
dst_bytes.memcpy(&src_bytes, len);
fn as_bytes(&self) -> Ptr<u8> {
self.reinterpret_cast::<u8>()
}

fn as_any(&self) -> &dyn std::any::Any {
self
}

fn equals(&self, other: &dyn ErasedPtr) -> Option<bool> {
if self.pointee_type_id() != other.pointee_type_id() {
return None;
}

if let Some(other_ptr) = other.as_any().downcast_ref::<Ptr<T>>() {
return Some(self == other_ptr);
}

None
fn equals(&self, other: &dyn ErasedPtr) -> bool {
other.as_any().downcast_ref::<Ptr<T>>() == Some(self)
}

fn is_null(&self) -> bool {
Expand Down Expand Up @@ -1118,66 +1102,28 @@ impl AnyPtr {
}
self.ptr.as_any().downcast_ref::<Ptr<T>>().cloned()
}

pub fn reinterpret_cast<T: ByteRepr>(&self) -> Ptr<T> {
macro_rules! try_src {
($ty:ty) => {{
if let Some(p) = self.cast::<$ty>() {
return p.reinterpret_cast::<T>();
}
if let Some(pv) = self.cast::<Vec<$ty>>() {
return pv.reinterpret_cast::<T>();
}
}};
}

try_src!(u8);
try_src!(i8);
try_src!(u16);
try_src!(i16);
try_src!(u32);
try_src!(i32);
try_src!(u64);
try_src!(i64);
try_src!(usize);
try_src!(isize);

panic!("reinterpret_cast: unsupported AnyPtr source");
}
}

impl PartialEq for AnyPtr {
fn eq(&self, other: &Self) -> bool {
let lhs: &dyn ErasedPtr = self.ptr.as_ref();
let rhs: &dyn ErasedPtr = other.ptr.as_ref();

lhs.equals(rhs).unwrap_or_default()
*self.ptr == *other.ptr
}
}

impl AnyPtr {
pub fn memcpy(&self, src: &AnyPtr, len: usize) {
let dst_erased = &*self.ptr;
let src_erased = &*src.ptr;

if dst_erased.pointee_type_id() == src_erased.pointee_type_id() {
dst_erased.memcpy(src_erased, len);
return;
}

let dst_u8: Ptr<u8> = self.reinterpret_cast();
let src_u8: Ptr<u8> = src.reinterpret_cast();
let dst_u8 = self.ptr.as_bytes();
let src_u8 = src.ptr.as_bytes();
dst_u8.memcpy(&src_u8, len);
}

pub fn memset(&self, value: u8, num: usize) {
let dst_u8: Ptr<u8> = self.reinterpret_cast();
dst_u8.memset(value, num);
self.ptr.as_bytes().memset(value, num);
}

pub fn memcmp(&self, other: &AnyPtr, len: usize) -> i32 {
let a: Ptr<u8> = self.reinterpret_cast();
let b: Ptr<u8> = other.reinterpret_cast();
let a = self.ptr.as_bytes();
let b = other.ptr.as_bytes();
a.memcmp(&b, len)
}
}
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/memcpy_struct_bytes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <assert.h>
#include <stdint.h>
#include <string.h>

struct point {
int32_t x;
int32_t y;
};

int main(void) {
struct point src = {3, 7};

unsigned char buf[sizeof(struct point)];
memcpy(buf, &src, sizeof(buf));

struct point dst;
memcpy(&dst, buf, sizeof(dst));

assert(dst.x == 3);
assert(dst.y == 7);

return 0;
}
58 changes: 58 additions & 0 deletions tests/unit/out/refcount/memcpy_struct_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
#[derive(Default)]
pub struct point {
pub x: Value<i32>,
pub y: Value<i32>,
}
impl ByteRepr for point {
fn byte_size() -> usize {
8
}
fn to_bytes(&self, buf: &mut [u8]) {
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
(*self.y.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
y: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let src: Value<point> = Rc::new(RefCell::new(point {
x: Rc::new(RefCell::new(3)),
y: Rc::new(RefCell::new(7)),
}));
let buf: Value<Box<[u8]>> = Rc::new(RefCell::new(
(0..8).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
));
{
((buf.as_pointer() as Ptr<u8>) as Ptr<u8>).to_any().memcpy(
&((src.as_pointer()) as Ptr<point>).to_any(),
::std::mem::size_of::<[u8; 8]>() as usize,
);
((buf.as_pointer() as Ptr<u8>) as Ptr<u8>).to_any().clone()
};
let dst: Value<point> = <Value<point>>::default();
{
((dst.as_pointer()) as Ptr<point>).to_any().memcpy(
&((buf.as_pointer() as Ptr<u8>) as Ptr<u8>).to_any(),
8usize as usize,
);
((dst.as_pointer()) as Ptr<point>).to_any().clone()
};
assert!(((((*(*dst.borrow()).x.borrow()) == 3) as i32) != 0));
assert!(((((*(*dst.borrow()).y.borrow()) == 7) as i32) != 0));
return 0;
}
47 changes: 47 additions & 0 deletions tests/unit/out/unsafe/memcpy_struct_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
extern crate libc;
use libc::*;
extern crate libcc2rs;
use libcc2rs::*;
use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct point {
pub x: i32,
pub y: i32,
}
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut src: point = point { x: 3, y: 7 };
let mut buf: [u8; 8] = [0_u8; 8];
{
if ::std::mem::size_of::<[u8; 8]>() != 0 {
::std::ptr::copy_nonoverlapping(
((&mut src as *mut point) as *const point as *const ::libc::c_void),
(buf.as_mut_ptr() as *mut u8 as *mut ::libc::c_void),
::std::mem::size_of::<[u8; 8]>() as usize,
)
}
(buf.as_mut_ptr() as *mut u8 as *mut ::libc::c_void)
};
let mut dst: point = <point>::default();
{
if ::std::mem::size_of::<point>() != 0 {
::std::ptr::copy_nonoverlapping(
(buf.as_mut_ptr() as *const u8 as *const ::libc::c_void),
((&mut dst as *mut point) as *mut point as *mut ::libc::c_void),
::std::mem::size_of::<point>() as usize,
)
}
((&mut dst as *mut point) as *mut point as *mut ::libc::c_void)
};
assert!(((((dst.x) == (3)) as i32) != 0));
assert!(((((dst.y) == (7)) as i32) != 0));
return 0;
}
Loading