1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use crate::interfaces::{nsIInterfaceRequestor, nsISupports};
6 use crate::{GetterAddrefs, RefCounted, RefPtr};
7 
8 #[repr(C)]
9 #[derive(Copy, Clone, Eq, PartialEq)]
10 /// A "unique identifier". This is modeled after OSF DCE UUIDs.
11 pub struct nsID(pub u32, pub u16, pub u16, pub [u8; 8]);
12 
13 /// Interface IDs
14 pub type nsIID = nsID;
15 /// Class IDs
16 pub type nsCID = nsID;
17 
18 /// A type which implements XpCom must follow the following rules:
19 ///
20 /// * It must be a legal XPCOM interface.
21 /// * The result of a QueryInterface or similar call, passing IID, must return a
22 ///   valid reference to an object of the given type.
23 /// * It must be valid to cast a &self reference to a &nsISupports reference.
24 pub unsafe trait XpCom: RefCounted {
25     const IID: nsIID;
26 
27     /// Perform a QueryInterface call on this object, attempting to dynamically
28     /// cast it to the requested interface type. Returns Some(RefPtr<T>) if the
29     /// cast succeeded, and None otherwise.
query_interface<T: XpCom>(&self) -> Option<RefPtr<T>>30     fn query_interface<T: XpCom>(&self) -> Option<RefPtr<T>> {
31         let mut ga = GetterAddrefs::<T>::new();
32         unsafe {
33             if (*(self as *const Self as *const nsISupports))
34                 .QueryInterface(&T::IID, ga.void_ptr())
35                 .succeeded()
36             {
37                 ga.refptr()
38             } else {
39                 None
40             }
41         }
42     }
43 
44     /// Perform a `GetInterface` call on this object, returning `None` if the
45     /// object doesn't implement `nsIInterfaceRequestor`, or can't access the
46     /// interface `T`.
get_interface<T: XpCom>(&self) -> Option<RefPtr<T>>47     fn get_interface<T: XpCom>(&self) -> Option<RefPtr<T>> {
48         let ireq = self.query_interface::<nsIInterfaceRequestor>()?;
49 
50         let mut ga = GetterAddrefs::<T>::new();
51         unsafe {
52             if ireq.GetInterface(&T::IID, ga.void_ptr()).succeeded() {
53                 ga.refptr()
54             } else {
55                 None
56             }
57         }
58     }
59 }
60