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 #![allow(non_snake_case)]
6 
7 #[macro_use]
8 extern crate xpcom;
9 
10 extern crate nserror;
11 
12 use nserror::{nsresult, NS_OK};
13 use std::ffi::{CStr, CString};
14 use std::os::raw::c_char;
15 use std::ptr;
16 use xpcom::interfaces;
17 
18 #[no_mangle]
Rust_ObserveFromRust() -> *const interfaces::nsIObserverService19 pub unsafe extern "C" fn Rust_ObserveFromRust() -> *const interfaces::nsIObserverService {
20     let obssvc = xpcom::services::get_ObserverService().unwrap();
21 
22     // Define an observer
23     #[derive(xpcom)]
24     #[xpimplements(nsIObserver)]
25     #[refcnt = "nonatomic"]
26     struct InitObserver {
27         run: *mut bool,
28     }
29     impl Observer {
30         unsafe fn Observe(
31             &self,
32             _subject: *const interfaces::nsISupports,
33             topic: *const c_char,
34             _data: *const i16,
35         ) -> nsresult {
36             *self.run = true;
37             assert!(CStr::from_ptr(topic).to_str() == Ok("test-rust-observe"));
38             NS_OK
39         }
40     }
41 
42     let topic = CString::new("test-rust-observe").unwrap();
43 
44     let mut run = false;
45     let observer = Observer::allocate(InitObserver { run: &mut run });
46     let rv = obssvc.AddObserver(
47         observer.coerce::<interfaces::nsIObserver>(),
48         topic.as_ptr(),
49         false,
50     );
51     assert!(rv.succeeded());
52 
53     let rv = obssvc.NotifyObservers(ptr::null(), topic.as_ptr(), ptr::null());
54     assert!(rv.succeeded());
55     assert!(run, "The observer should have been run!");
56 
57     let rv = obssvc.RemoveObserver(observer.coerce::<interfaces::nsIObserver>(), topic.as_ptr());
58     assert!(rv.succeeded());
59 
60     assert!(
61         observer.coerce::<interfaces::nsISupports>() as *const _
62             == &*observer
63                 .query_interface::<interfaces::nsISupports>()
64                 .unwrap() as *const _
65     );
66 
67     &*obssvc
68 }
69 
70 #[no_mangle]
Rust_ImplementRunnableInRust( it_worked: *mut bool, runnable: *mut *const interfaces::nsIRunnable, )71 pub unsafe extern "C" fn Rust_ImplementRunnableInRust(
72     it_worked: *mut bool,
73     runnable: *mut *const interfaces::nsIRunnable,
74 ) {
75     // Define a type which implements nsIRunnable in rust.
76     #[derive(xpcom)]
77     #[xpimplements(nsIRunnable)]
78     #[refcnt = "atomic"]
79     struct InitMyRunnable {
80         it_worked: *mut bool,
81     }
82 
83     impl MyRunnable {
84         unsafe fn Run(&self) -> nsresult {
85             *self.it_worked = true;
86             NS_OK
87         }
88     }
89 
90     // Create my runnable type, and forget it into the outparameter!
91     let my_runnable = MyRunnable::allocate(InitMyRunnable {
92         it_worked: it_worked,
93     });
94     my_runnable
95         .query_interface::<interfaces::nsIRunnable>()
96         .unwrap()
97         .forget(&mut *runnable);
98 }
99