1#[doc = include_str!("../README.md")]
2
3#[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}