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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! Procedural macro attributes for defining intercom libraries.
//!
//! These macros implement various low level items that enable the associated
//! types to be instantiated and invoked over the COM interface protocol.
//!
//! **Instead of depending on this crate directly, the users should depend on
//! the main `intercom` crate isntead.**
//!
//! The split into two crates is an artificial limitation of Rust. The crates
//! defining procedural macros cannot export anything else than procedural
//! macros.

#![allow(unused_imports)]

extern crate intercom_common;
use intercom_common::attributes::*;

extern crate proc_macro;
use proc_macro::{LexError, TokenStream};

// Note the rustdoc comments on the [proc_macro_attribute] functions document
// "attributes", not "functions".
//
// While at "com_interface" function creates virtual tables, etc. when it is
// invoked, the attribute doesn't "creates" these. Instead the attribute just
// "defines" the trait/impl as a COM interface.
//
// The runtime documentation for developers is present in the expand_...
// methods below.

/// Defines an intercom interface.
///
/// ```rust,ignore
/// #[com_interface(IID, base?)]
/// trait Foo { /* ... */ }
/// ```
///
/// - `IID` - A unique ID of the interface used to query for it. Must be either
///           a valid GUID or `AUTO_GUID` specifier.
/// - `base` - Base interface. Defaults to `IUnknown` if not specified.
///
/// Associated types: `trait`, `impl Struct`
///
/// Intercom interfaces form the basis of the cross language API provided by
/// the user library. The interfaces define the available methods that can be
/// called through the interface pointers given to the clients.
///
/// Each interface automatically inherits from the base `IUnknown` interface,
/// which provides the clients a way to perform reference counting and the
/// ability to query for other interfaces the object might implement.
#[proc_macro_attribute]
pub fn com_interface(attr: TokenStream, tokens: TokenStream) -> TokenStream
{
    match expand_com_interface(attr, tokens) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Defines a COM class that implements one or more COM interfaces.
///
/// ```rust,ignore
/// #[com_class(CLSID, interfaces...)]
/// struct S { /* ... */ }
/// ```
///
/// - `CLSID` - A unique ID of the exposed class. The clients use the class ID
///             to specify the class when they want to construct an object.
///             The value must be a valid GUID, `AUTO_GUID` or `NO_GUID`.
/// - `interfaces` - Any number of interfaces that the class implements.
///
/// Associated types: `struct`, `enum`
///
/// If the `CLSID` is specified as `NO_GUID`, the class cannot be constructed
/// by the clients. It can still be returned as a return value from other
/// intercom methods.
#[proc_macro_attribute]
pub fn com_class(attr: TokenStream, tokens: TokenStream) -> TokenStream
{
    match expand_com_class(attr, tokens) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Defines a COM library sub-module.
///
/// ```rust,ignore
/// com_module!(items...)]
/// ```
///
/// - `items` - List of items contained in this module.
///
/// The macro results in the implementation of the object creation
/// infrastructure that allows external clients to load the library and
/// instantiate the specified types.
#[proc_macro]
pub fn com_module(args: TokenStream) -> TokenStream
{
    match expand_com_module(args, false) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Defines the COM library.
///
/// ```rust,ignore
/// com_library!( libid = "...", items...)]
/// ```
///
/// - `libid` - A unique ID that specifies the current intercom library.
///             Optional, the libid is generated randomly if omitted.
/// - `items` - List of items contained in this library.
///
/// The macro results in the implementation of the object creation
/// infrastructure that allows external clients to load the library and
/// instantiate the specified types.
#[proc_macro]
pub fn com_library(args: TokenStream) -> TokenStream
{
    match expand_com_module(args, true) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Derives the implementation of the trait ForeignType for a type.
#[proc_macro_derive(ForeignType)]
pub fn named_type_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream
{
    match expand_bidirectional_type_info(input) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Derives the implementation of the trait ExternType for a type.
#[proc_macro_derive(ExternType)]
pub fn derive_extern_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream
{
    match expand_derive_extern_type(input) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Derives the implementation of the trait ExternInput for a type.
#[proc_macro_derive(ExternInput)]
pub fn derive_extern_input(input: proc_macro::TokenStream) -> proc_macro::TokenStream
{
    match expand_derive_extern_input(input) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}

/// Derives the implementation of the trait ExternOutput for a type.
#[proc_macro_derive(ExternOutput)]
pub fn derive_extern_output(input: proc_macro::TokenStream) -> proc_macro::TokenStream
{
    match expand_derive_extern_output(input) {
        Ok(t) => t,
        Err(e) => panic!("{}", e),
    }
}