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
use ::prelude::*;
use super::*;
use ::guid::GUID;
use ::syn::{ LitStr, Path };
intercom_attribute!(
ComLibraryAttr< ComLibraryAttrParam, Path > {
libid : LitStr,
}
);
#[derive(Debug, PartialEq)]
pub struct ComLibrary {
name : String,
libid : GUID,
coclasses : Vec<Path>,
}
impl ComLibrary
{
pub fn parse(
crate_name : &str,
attr_params : TokenStream,
) -> ParseResult<ComLibrary>
{
let attr : ComLibraryAttr = ::syn::parse2( attr_params )
.map_err( |_| ParseError::ComLibrary(
"Attribute syntax error".into() ) )?;
let libid = match attr.libid().map_err( ParseError::ComLibrary )? {
Some( libid ) => GUID::parse( &libid.value() )
.map_err( ParseError::ComLibrary )?,
None => ::utils::generate_libid( crate_name )
} ;
Ok( ComLibrary {
name: crate_name.to_owned(),
coclasses: attr.args().into_iter().cloned().collect(),
libid,
} )
}
pub fn name( &self ) -> &str { &self.name }
pub fn libid( &self ) -> &GUID { &self.libid }
pub fn coclasses( &self ) -> &[Path] { &self.coclasses }
pub fn add_coclass( &mut self, clsid : Path ) { self.coclasses.push( clsid ) }
}
#[cfg(test)]
mod test
{
use super::*;
#[test]
fn parse_com_library() {
let lib = ComLibrary::parse(
"library_name".into(),
quote!( libid = "12345678-1234-1234-1234-567890ABCDEF",
Foo, Bar ) )
.expect( "com_library attribute parsing failed" );
assert_eq!( lib.name(), "library_name" );
assert_eq!( lib.libid(), &GUID {
data1: 0x12345678,
data2: 0x1234,
data3: 0x1234,
data4: [ 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF ]
} );
assert_eq!( lib.coclasses().len(), 2 );
assert_eq!( lib.coclasses()[0], parse_quote!( Foo ) );
assert_eq!( lib.coclasses()[1], parse_quote!( Bar ) );
}
#[test]
fn parse_com_library_with_auto_guid() {
let lib = ComLibrary::parse(
"another_library".into(),
quote!( One, Two ) )
.expect( "com_library attribute parsing failed" );
assert_eq!( lib.name(), "another_library" );
assert_eq!(
lib.libid(),
&GUID::parse( "696B2FAE-AC56-3E08-7C2C-ABAA8DB8F6E3" ).unwrap() );
assert_eq!( lib.coclasses().len(), 2 );
assert_eq!( lib.coclasses()[0], parse_quote!( One ) );
assert_eq!( lib.coclasses()[1], parse_quote!( Two ) );
}
#[test]
fn parse_com_library_with_empty_parameters() {
let lib = ComLibrary::parse( "lib".into(), quote!() ).unwrap();
assert_eq!( lib.coclasses().len(), 0 );
assert_eq!(
lib.libid(),
&GUID::parse( "22EC0095-CD17-3AFD-6C4F-531464178911" ).unwrap() );
}
}