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
/// Defines a writer expression from another expression, unsafe function or extern function.
///
/// If unsafe function specified as argument
/// it just creates an `FnMut` wrapper that calls unsafe fn in unsafe block.
/// The function can be specified by identifier or by braced full path.
/// See [Safety](#safety) section for important details about safety.
///
/// If extern function specified as argument
/// it creates extern block with this function and
/// creates an `FnMut` wrapper that calls unsafe fn in unsafe block.
/// See [Safety](#safety) section for important details about safety.
///
/// If an expression given as argument, the macro just returns it as a result.
///
/// This macro is used by [`define_writer`], [`define_try_writer`] macros.
///
/// # Safety
///
/// Note that writing using writer expression
/// defined with `unsafe fn` or `extern `fn` do not require unsafe,
/// so defining writer expression itself should be treated as an unsafe operation.
///
/// [`define_writer`]: macro.define_writer.htm
/// [`define_try_writer`]: macro.define_try_writer.htm
#[macro_export]
macro_rules! define_writer_expr {
    ( unsafe fn $func:ident($ty1:ty) $( -> $ret:ty)? ) => {
        |arg1: $ty1| unsafe {
            #[allow(unused_qualifications)]
            $func(arg1)
        }
    };
    ( unsafe fn ($func:path)($ty1:ty) $( -> $ret:ty)? ) => {
        |arg1: $ty1| unsafe {
            #[allow(unused_qualifications)]
            $func(arg1)
        }
    };
    ( unsafe fn $func:ident($ty1:ty, $ty2:ty) $( -> $ret:ty)? ) => {
        |arg1: $ty1, arg2: $ty2| unsafe {
            #[allow(unused_qualifications)]
            $func(arg1, arg2)
        }
    };
    ( unsafe fn ($func:path)($ty1:ty, $ty2:ty) $( -> $ret:ty)? ) => {
        |arg1: $ty1, arg2: $ty2| unsafe {
            #[allow(unused_qualifications)]
            $func(arg1, arg2)
        }
    };
    ( $(#[$extern_meta:meta])* extern $($abi:literal)?
        $(#[$meta:meta])* fn $func:ident($arg1:tt: $ty1:ty) $( -> $ret:ty)?
    ) => {{
        $(#[$extern_meta])* extern $($abi)? {
            $(#[$meta])* fn $func($arg1: $ty1) $( -> $ret)?;
        }
        |arg1: $ty1| unsafe { $func(arg1) }
    }};
    ( $(#[$extern_meta:meta])* extern $($abi:literal)?
        $(#[$meta:meta])* fn $func:ident($arg1:tt: $ty1:ty, $arg2:tt: $ty2:ty) $( -> $ret:ty)?
    ) => {{
        $(#[$extern_meta])* extern $($abi)? {
            $(#[$meta])* fn $func($arg1: $ty1, $arg2: $ty2) $( -> $ret)?;
        }
        |arg1: $ty1, arg2: $ty2| unsafe { $func(arg1, arg2) }
    }};
    ( $expr:expr ) => {
        $expr
    };
}