pub fn git(args: &[String]) -> Result<String, String> {
imp::git(args)
}
#[cfg(target_arch = "wasm32")]
mod imp {
use crate::bindings::diffr::plugin::host;
pub(super) fn git(args: &[String]) -> Result<String, String> {
host::git(args)
}
}
#[cfg(not(target_arch = "wasm32"))]
pub trait Host {
fn git(&self, args: &[String]) -> Result<String, String>;
}
#[cfg(not(target_arch = "wasm32"))]
pub fn scope<R>(host: std::rc::Rc<dyn Host>, call: impl FnOnce() -> R) -> R {
imp::scope(host, call)
}
#[cfg(not(target_arch = "wasm32"))]
mod imp {
use super::Host;
use std::cell::RefCell;
use std::rc::Rc;
thread_local! {
static CURRENT: RefCell<Option<Rc<dyn Host>>> = const { RefCell::new(None) };
}
struct Restore(Option<Rc<dyn Host>>);
impl Drop for Restore {
fn drop(&mut self) {
CURRENT.with(|current| *current.borrow_mut() = self.0.take());
}
}
pub(super) fn scope<R>(host: Rc<dyn Host>, call: impl FnOnce() -> R) -> R {
let _restore = Restore(CURRENT.with(|current| current.borrow_mut().replace(host)));
call()
}
fn current() -> Rc<dyn Host> {
CURRENT.with(|current| {
current
.borrow()
.clone()
.expect("the host function is called only while diffr runs a plugin")
})
}
pub(super) fn git(args: &[String]) -> Result<String, String> {
current().git(args)
}
}