Skip to content

Commit b7d5285

Browse files
committed
Add VaArgGet for AnyPtr
1 parent 6b0264a commit b7d5285

4 files changed

Lines changed: 268 additions & 0 deletions

File tree

libcc2rs/src/va_args.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ impl<T: 'static + crate::ByteRepr> VaArgGet for crate::rc::Ptr<T> {
128128
}
129129
}
130130

131+
impl VaArgGet for crate::rc::AnyPtr {
132+
fn get(v: &VaArg) -> Self {
133+
match v {
134+
VaArg::Ptr(any) => any.clone(),
135+
_ => panic!("VaArgGet: expected Ptr"),
136+
}
137+
}
138+
}
139+
131140
impl<T: 'static> From<crate::FnPtr<T>> for VaArg {
132141
fn from(v: crate::FnPtr<T>) -> Self {
133142
VaArg::Ptr(v.to_any())
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Default)]
10+
pub struct registry {
11+
pub slot: Value<AnyPtr>,
12+
pub level: Value<i64>,
13+
}
14+
impl Clone for registry {
15+
fn clone(&self) -> Self {
16+
Self {
17+
slot: Rc::new(RefCell::new((*self.slot.borrow()).clone())),
18+
level: Rc::new(RefCell::new((*self.level.borrow()).clone())),
19+
}
20+
}
21+
}
22+
impl ByteRepr for registry {
23+
fn byte_size() -> usize {
24+
16
25+
}
26+
fn to_bytes(&self, buf: &mut [u8]) {
27+
(*self.slot.borrow()).to_bytes(&mut buf[0..8]);
28+
(*self.level.borrow()).to_bytes(&mut buf[8..16]);
29+
}
30+
fn from_bytes(buf: &[u8]) -> Self {
31+
Self {
32+
slot: Rc::new(RefCell::new(<AnyPtr>::from_bytes(&buf[0..8]))),
33+
level: Rc::new(RefCell::new(<i64>::from_bytes(&buf[8..16]))),
34+
}
35+
}
36+
}
37+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
38+
enum field {
39+
#[default]
40+
FIELD_SLOT = 0,
41+
FIELD_LEVEL = 1,
42+
}
43+
impl From<i32> for field {
44+
fn from(n: i32) -> field {
45+
match n {
46+
0 => field::FIELD_SLOT,
47+
1 => field::FIELD_LEVEL,
48+
_ => panic!("invalid field value: {}", n),
49+
}
50+
}
51+
}
52+
libcc2rs::impl_enum_inc_dec!(field);
53+
impl ByteRepr for field {
54+
fn to_bytes(&self, buf: &mut [u8]) {
55+
(*self as i32).to_bytes(buf);
56+
}
57+
fn from_bytes(buf: &[u8]) -> Self {
58+
<field>::from(i32::from_bytes(buf))
59+
}
60+
}
61+
pub fn registry_update_0(r: Ptr<registry>, field: field, __args: &[VaArg]) -> i32 {
62+
let r: Value<Ptr<registry>> = Rc::new(RefCell::new(r));
63+
let field: Value<field> = Rc::new(RefCell::new(field));
64+
let result: Value<i32> = Rc::new(RefCell::new(0));
65+
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
66+
(*ap.borrow_mut()) = VaList::new(__args);
67+
'switch: {
68+
let __match_cond = ((*field.borrow()) as u32);
69+
match __match_cond {
70+
__v if __v == ((field::FIELD_SLOT as i32) as u32) => {
71+
(*(*(*r.borrow()).upgrade().deref()).slot.borrow_mut()) =
72+
((*ap.borrow_mut()).arg::<AnyPtr>()).clone();
73+
break 'switch;
74+
}
75+
__v if __v == ((field::FIELD_LEVEL as i32) as u32) => {
76+
(*(*(*r.borrow()).upgrade().deref()).level.borrow_mut()) =
77+
((*ap.borrow_mut()).arg::<i64>()).clone();
78+
break 'switch;
79+
}
80+
_ => {
81+
(*result.borrow_mut()) = 1;
82+
break 'switch;
83+
}
84+
}
85+
};
86+
return (*result.borrow());
87+
}
88+
pub fn main() {
89+
std::process::exit(main_0());
90+
}
91+
fn main_0() -> i32 {
92+
let r: Value<registry> = Rc::new(RefCell::new(registry {
93+
slot: Rc::new(RefCell::new(AnyPtr::default())),
94+
level: Rc::new(RefCell::new(0_i64)),
95+
}));
96+
let payload: Value<i32> = Rc::new(RefCell::new(7));
97+
assert!(
98+
(((({
99+
registry_update_0(
100+
(r.as_pointer()),
101+
field::FIELD_SLOT,
102+
&[(payload.as_pointer()).into()],
103+
)
104+
}) == 0) as i32)
105+
!= 0)
106+
);
107+
assert!(
108+
(((({ registry_update_0((r.as_pointer()), field::FIELD_LEVEL, &[(5_i64).into(),]) }) == 0)
109+
as i32)
110+
!= 0)
111+
);
112+
assert!(
113+
((({
114+
let _lhs = (*(*r.borrow()).slot.borrow()).clone();
115+
_lhs == (payload.as_pointer()).to_any()
116+
}) as i32)
117+
!= 0)
118+
);
119+
assert!(
120+
(((((*(*r.borrow()).slot.borrow())
121+
.reinterpret_cast::<i32>()
122+
.read())
123+
== 7) as i32)
124+
!= 0)
125+
);
126+
assert!(((((*(*r.borrow()).level.borrow()) == 5_i64) as i32) != 0));
127+
return 0;
128+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone, Default)]
11+
pub struct registry {
12+
pub slot: *mut ::libc::c_void,
13+
pub level: i64,
14+
}
15+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
16+
enum field {
17+
#[default]
18+
FIELD_SLOT = 0,
19+
FIELD_LEVEL = 1,
20+
}
21+
impl From<i32> for field {
22+
fn from(n: i32) -> field {
23+
match n {
24+
0 => field::FIELD_SLOT,
25+
1 => field::FIELD_LEVEL,
26+
_ => panic!("invalid field value: {}", n),
27+
}
28+
}
29+
}
30+
libcc2rs::impl_enum_inc_dec!(field);
31+
pub unsafe fn registry_update_0(mut r: *mut registry, mut field: field, __args: &[VaArg]) -> i32 {
32+
let mut result: i32 = 0;
33+
let mut ap: VaList = VaList::default();
34+
ap = VaList::new(__args);
35+
'switch: {
36+
let __match_cond = (field as u32);
37+
match __match_cond {
38+
__v if __v == ((field::FIELD_SLOT as i32) as u32) => {
39+
(*r).slot = ap.arg::<*mut ::libc::c_void>();
40+
break 'switch;
41+
}
42+
__v if __v == ((field::FIELD_LEVEL as i32) as u32) => {
43+
(*r).level = (ap.arg::<i64>()).clone();
44+
break 'switch;
45+
}
46+
_ => {
47+
result = 1;
48+
break 'switch;
49+
}
50+
}
51+
};
52+
return result;
53+
}
54+
pub fn main() {
55+
unsafe {
56+
std::process::exit(main_0() as i32);
57+
}
58+
}
59+
unsafe fn main_0() -> i32 {
60+
let mut r: registry = registry {
61+
slot: std::ptr::null_mut(),
62+
level: 0_i64,
63+
};
64+
let mut payload: i32 = 7;
65+
assert!(
66+
((((unsafe {
67+
registry_update_0(
68+
(&mut r as *mut registry),
69+
field::FIELD_SLOT,
70+
&[(&mut payload as *mut i32).into()],
71+
)
72+
}) == (0)) as i32)
73+
!= 0)
74+
);
75+
assert!(
76+
((((unsafe {
77+
registry_update_0(
78+
(&mut r as *mut registry),
79+
field::FIELD_LEVEL,
80+
&[(5_i64).into()],
81+
)
82+
}) == (0)) as i32)
83+
!= 0)
84+
);
85+
assert!(((((r.slot) == ((&mut payload as *mut i32) as *mut ::libc::c_void)) as i32) != 0));
86+
assert!(((((*(r.slot as *mut i32)) == (7)) as i32) != 0));
87+
assert!(((((r.level) == (5_i64)) as i32) != 0));
88+
return 0;
89+
}

tests/unit/va_arg_void_ptr.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <assert.h>
2+
#include <stdarg.h>
3+
4+
struct registry {
5+
void *slot;
6+
long level;
7+
};
8+
9+
enum field {
10+
FIELD_SLOT,
11+
FIELD_LEVEL,
12+
};
13+
14+
static int registry_update(struct registry *r, enum field field, ...) {
15+
int result = 0;
16+
va_list ap;
17+
va_start(ap, field);
18+
switch (field) {
19+
case FIELD_SLOT:
20+
r->slot = va_arg(ap, void *);
21+
break;
22+
case FIELD_LEVEL:
23+
r->level = va_arg(ap, long);
24+
break;
25+
default:
26+
result = 1;
27+
break;
28+
}
29+
va_end(ap);
30+
return result;
31+
}
32+
33+
int main() {
34+
struct registry r = {0, 0};
35+
int payload = 7;
36+
assert(registry_update(&r, FIELD_SLOT, &payload) == 0);
37+
assert(registry_update(&r, FIELD_LEVEL, 5L) == 0);
38+
assert(r.slot == (void *)&payload);
39+
assert(*(int *)r.slot == 7);
40+
assert(r.level == 5);
41+
return 0;
42+
}

0 commit comments

Comments
 (0)