astd/
macros.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/// A simple macro that ignores all of its contents and does nothing.
///
/// # Use
///
/// This macro exists to enable expansion of repeat or optional rule groups
/// that may not explicitly make use of that argument. For example, sometimes
/// the conditional inclusion of a token might want to generate something not
/// using that meta-variable -- but expansion requires at least one meta-variable
/// from the group to be specified to not be ambiguous. With this macro, you can
/// still "use" the meta-variable without actually actively using it.
///
/// # Example
///
/// ```
/// # use astd::phantom_fragment;
/// macro_rules! generate{
///   ($A:ident, $($B:ident)?) => {
///     $(
///       phantom_fragment!($B);
///       impl $A {
///         // When $B is present, define this function without using $B.
///         fn do_something(&self) { /* ... */ }
///       }
///     )?
///   }
/// }
/// ```
#[macro_export]
macro_rules! phantom_fragment {
  ($($_:tt)*) => {};
  ($_:block) => {};
  ($_:expr) => {};
  ($_:ident) => {};
  ($_:item) => {};
  ($_:lifetime) => {};
  ($_:literal) => {};
  ($_:meta) => {};
  ($_:pat) => {};
  ($_:pat_param) => {};
  ($_:path) => {};
  ($_:stmt) => {};
  ($_:ty) => {};
  ($_:vis) => {};
}

/// Defines the input types as being transparent wrappers around another type,
/// which enables conversions between reference types.
#[macro_export]
macro_rules! transparent {
  ($($Outter:ident.$Ex:tt => $Inner:ty$(,)?)+) => {
    $(
      unsafe impl $crate::convert::Transparent for $Outter {
        type Wrapped = $Inner;
      }

      impl AsRef<$Inner> for $Outter {
        fn as_ref(&self) -> &$Inner {
          &self.$Ex
        }
      }

      impl AsMut<$Inner> for $Outter {
        fn as_mut(&mut self) -> &mut $Inner {
          &mut self.$Ex
        }
      }

      impl ::astd::convert::Take<$Inner> for $Outter {
        unsafe fn take(self) -> $Inner {
          self.$Ex
        }
      }

      impl std::ops::Deref for $Outter {
        type Target = $Inner;
        fn deref(&self) -> &Self::Target {
          &self.$Ex
        }
      }

      impl std::ops::DerefMut for $Outter {
        fn deref_mut(&mut self) -> &mut Self::Target {
          &mut self.$Ex
        }
      }
    )+
  };
}