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