use std::{cell::RefCell, rc::Rc}; use napi::bindgen_prelude::*; pub struct Repository { dir: String, } impl Repository { fn remote(&self) -> Remote { Remote { inner: self } } } pub struct Remote<'repo> { inner: &'repo Repository, } impl<'repo> Remote<'repo> { fn name(&self) -> String { "origin".to_owned() } } #[napi] pub struct JsRepo { inner: Repository, } #[napi] impl JsRepo { #[napi(constructor)] pub fn new(dir: String) -> Self { JsRepo { inner: Repository { dir }, } } #[napi] pub fn remote(&self, reference: Reference, env: Env) -> Result { Ok(JsRemote { inner: reference.share_with(env, |repo| Ok(repo.inner.remote()))?, }) } } #[napi] pub struct JsRemote { inner: SharedReference>, } #[napi] impl JsRemote { #[napi] pub fn name(&self) -> String { self.inner.name() } } struct OwnedStyleSheet { rules: Vec, } #[napi] pub struct CSSRuleList { owned: Rc>, } #[napi] impl CSSRuleList { #[napi] pub fn get_rules(&self) -> Vec { self.owned.borrow().rules.to_vec() } } #[napi] pub struct CSSStyleSheet { inner: Rc>, rules: Option>, } #[napi] pub struct AnotherCSSStyleSheet { inner: Rc>, rules: Reference, } #[napi] impl AnotherCSSStyleSheet { #[napi(getter)] pub fn rules(&self, env: Env) -> Result> { self.rules.clone(env) } } #[napi] impl CSSStyleSheet { #[napi(constructor)] pub fn new(rules: Vec) -> Result { let inner = Rc::new(RefCell::new(OwnedStyleSheet { rules })); Ok(CSSStyleSheet { inner, rules: None }) } #[napi(getter)] pub fn rules(&mut self, env: Env) -> Result> { if let Some(rules) = &self.rules { return rules.clone(env); } let rules = CSSRuleList::into_reference( CSSRuleList { owned: self.inner.clone(), }, env, )?; self.rules = Some(rules.clone(env)?); Ok(rules) } #[napi] pub fn another_css_style_sheet(&self, env: Env) -> Result { Ok(AnotherCSSStyleSheet { inner: self.inner.clone(), rules: self.rules.as_ref().unwrap().clone(env)?, }) } }