Skip to main content

ptr_arrow/
lib.rs

1#[doc = include_str!("../README.md")]
2
3/// Wraps an expression with C-style arrow syntax.
4/// 
5/// See the [crate-level documentation][crate] for more info.
6#[macro_export]
7macro_rules! arrow {
8	($($tt:tt)*) => ($crate::__arrow_internal!([] $($tt)*));
9}
10
11#[doc(hidden)]
12#[macro_export]
13macro_rules! __arrow_internal {
14	([ $($current:tt)* ] -> $base:ident $(::$path:ident)+ ($($args:tt)*)) => {
15		$base$(::$path)*($($current)*, $($args)*)
16	};
17	([ $($current:tt)* ] [-> $index:expr] $($rest:tt)*) => {
18		$crate::__arrow_internal!([ (*($($current)*).add($index)) ] $($rest)*)
19	};
20	([ $($current:tt)* ] -> $($rest:tt)*) => {
21		$crate::__arrow_internal!([ (*($($current)*)) ] . $($rest)*)
22	};
23	([ $($current:tt)*] $next:tt $($rest:tt)*) => {
24		$crate::__arrow_internal!([ $($current)* $next ] $($rest)*)
25	};
26	([ $($current:tt)* ]) => ($($current)*);
27}
28
29#[test]
30fn test() {
31	struct A {
32		b: *mut B,
33	}
34	struct B {
35		c: *mut C,
36	}
37	struct C {
38		n: i32,
39		array: *mut i32,
40	}
41	impl C {
42		unsafe fn get_n_method(&self) -> i32 { self.n }
43		unsafe fn get_n_ptr(this: *mut C) -> i32 { unsafe { (*this).n } }
44	}
45	let mut array = [0, 10, 20];
46	let mut c = C { n: 4, array: array.as_mut_ptr() };
47	let mut b = B { c: &mut c };
48	let a = A { b: &mut b };
49	unsafe {
50		assert_eq!(arrow!(a.b->c->n), 4);
51		assert_eq!(arrow!(a.b->c->get_n_method()), 4);
52		assert_eq!(arrow!(a.b->c->C::get_n_ptr()), 4);
53		assert_eq!(arrow!(a.b->c->array[->1]), 10);
54		arrow!(a.b->c->array[->0]) = 30;
55		assert_eq!(arrow!(a.b->c->array[->0]), 30);
56	}
57}