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