Skip to main content

ptr_arrow/
lib.rs

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