Skip to content

Commit

Permalink
Refactor browser and metal examples to use OnceCell
Browse files Browse the repository at this point in the history
  • Loading branch information
silvanshade committed Sep 3, 2023
1 parent a9ff910 commit 7761d9b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
35 changes: 22 additions & 13 deletions crates/icrate/examples/browser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![deny(unsafe_op_in_unsafe_fn)]
use core::{cell::RefCell, ptr::NonNull};
use core::{cell::OnceCell, ptr::NonNull};

use icrate::{
AppKit::{
Expand All @@ -26,20 +26,29 @@ use objc2::{
sel, ClassType,
};

type IdCell<T> = Box<RefCell<Option<Id<T>>>>;
type IdCell<T> = Box<OnceCell<Id<T>>>;

macro_rules! idcell {
($name:ident => $this:expr) => {
$this.$name.set($name).expect(&format!(
"ivar should not already be initialized: `{}`",
concat!(stringify!($name))
));
};
($name:ident <= $this:expr) => {
let $name = $this.$name.borrow();
let $name = $name
.as_ref()
.expect(concat!(stringify!($name), " ivar should be initialized"));
let Some($name) = $this.$name.get() else {
// NOTE: could use `core::hint::unreachable_unchecked` here
unreachable!(
"ivar should be initialized: `{}`",
concat!(stringify!($name))
)
};
};
}

declare_class!(
struct Delegate {
text_field: IvarDrop<IdCell<NSTextField>, "_text_field">,
nav_url: IvarDrop<IdCell<NSTextField>, "_nav_url">,
web_view: IvarDrop<IdCell<WKWebView>, "_web_view">,
window: IvarDrop<IdCell<NSWindow>, "_window">,
}
Expand All @@ -56,7 +65,7 @@ declare_class!(
unsafe fn init(this: *mut Self) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = msg_send![super(this), init];
this.map(|this| {
Ivar::write(&mut this.text_field, IdCell::default());
Ivar::write(&mut this.nav_url, IdCell::default());
Ivar::write(&mut this.web_view, IdCell::default());
Ivar::write(&mut this.window, IdCell::default());
NonNull::from(this)
Expand Down Expand Up @@ -234,9 +243,9 @@ declare_class!(
web_view.loadRequest(&request);
}

self.text_field.replace(Some(nav_url));
self.web_view.replace(Some(web_view));
self.window.replace(Some(window));
idcell!(nav_url => self);
idcell!(web_view => self);
idcell!(window => self);
}
}

Expand Down Expand Up @@ -270,10 +279,10 @@ declare_class!(
web_view: &WKWebView,
_navigation: Option<&WKNavigation>,
) {
idcell!(text_field <= self);
idcell!(nav_url <= self);
unsafe {
if let Some(url) = web_view.URL().and_then(|url| url.absoluteString()) {
text_field.setStringValue(&url);
nav_url.setStringValue(&url);
}
}
}
Expand Down
27 changes: 18 additions & 9 deletions crates/icrate/examples/metal.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![deny(unsafe_op_in_unsafe_fn)]

use core::{cell::RefCell, ptr::NonNull};
use core::{cell::OnceCell, ptr::NonNull};

use icrate::{
AppKit::{
Expand Down Expand Up @@ -101,14 +101,23 @@ pub struct Color {
pub b: f32,
}

type IdCell<T> = Box<RefCell<Option<Id<T>>>>;
type IdCell<T> = Box<OnceCell<Id<T>>>;

macro_rules! idcell {
($name:ident => $this:expr) => {
$this.$name.set($name).expect(&format!(
"ivar should not already be initialized: `{}`",
concat!(stringify!($name))
));
};
($name:ident <= $this:expr) => {
let $name = $this.$name.borrow();
let $name = $name
.as_ref()
.expect(concat!(stringify!($name), " ivar should be initialized"));
let Some($name) = $this.$name.get() else {
// NOTE: could use `core::hint::unreachable_unchecked` here
unreachable!(
"ivar should be initialized: `{}`",
concat!(stringify!($name))
)
};
};
}

Expand Down Expand Up @@ -231,9 +240,9 @@ declare_class!(
}

// initialize the delegate state
self.command_queue.replace(Some(command_queue));
self.pipeline_state.replace(Some(pipeline_state));
self.window.replace(Some(window));
idcell!(command_queue => self);
idcell!(pipeline_state => self);
idcell!(window => self);
}
}

Expand Down

0 comments on commit 7761d9b

Please sign in to comment.