Macro enso_shapely::shared[][src]

macro_rules! shared {
    ($name:ident $($in:tt)*) => { ... };
}
Expand description

This module implements the shared macro, an utility allowing for easy definition of Rc<RefCell<...>> wrappers. This macro provides an easy way to define secure Rc<RefCell<...>> wrappers for a given struct.

This macro accepts a body which is very similar to normal struct definition. There are a few notable differences:

  • The first token this macro accepts should be the name of the wrapped structure.
  • The implementation block does not have a name. It is always implemented for the struct. You are allowed to provide multiple impl blocks.

This macro traverses the definition and for each function, it generates a borrowing counterpart. It also handles the new function in a special way. Please note, that this macro generates only safe bindings. If your original function returns a reference, the generated code will fail. If you want to return references with some custom guard system, implement that outside of this macro usage.

For the given input:

shared! { Uniform

#[derive(Clone,Copy,Debug)]
pub struct UniformData<Value> {
    value: Value,
    dirty: bool,
}

impl<Value:UniformValue> {
    /// Constructor.
    pub fn new(value:Value) -> Self {
        let dirty = false;
        Self {value,dirty}
    }

    /// Checks whether the uniform was changed and not yet updated.
    pub fn check_dirty(&self) -> bool {
        self.dirty
    }

    /// Modifies the value stored by the uniform.
    pub fn modify<F:FnOnce(&mut Value)>(&mut self, f:F) {
        self.set_dirty();
        f(&mut self.value);
    }
}}

The following output will be generated:

#[derive(Clone,Copy,Debug)]
pub struct UniformData<Value> {
    value: Value,
    dirty: bool,
}

impl<Value:UniformValue> for UniformData<Value> {
    #[doc = r###"Constructor."###]
    pub fn new(value:Value) -> Self {
        let dirty = false;
        Self {value,dirty}
    }

    #[doc = r###"Checks whether the uniform was changed and not yet updated."###]
    pub fn check_dirty(&self) -> bool {
        self.dirty
    }

    #[doc = r###"Modifies the value stored by the uniform."###]
    pub fn modify<F:FnOnce(&mut Value)>(&mut self, f:F) {
        self.set_dirty();
        f(&mut self.value);
    }
}

#[derive(Clone,Copy,Debug)]
pub struct Uniform<Value> {
    rc: Rc<RefCell<UniformData<Value>>>
}

impl<Value:UniformValue> for Uniform<Value> {
    #[doc = r###"Constructor."###]
    pub fn new(value:Value) -> Self {
        let rc = Rc::new(RefCell::new(UniformData::new(value)));
        Self {rc}
    }

    #[doc = r###"Checks whether the uniform was changed and not yet updated."###]
    pub fn check_dirty(&self) -> bool {
        self.rc.borrow.check_dirty()
    }

    #[doc = r###"Modifies the value stored by the uniform."###]
    pub fn modify<F:FnOnce(&mut Value)>(&self, f:F) {
        self.borrow_mut().modify(f)
    }
}

Note Both the implementation as well as usage syntax of this macro will be nicer if it was implemented as procedural macro. However, no IDE supports expansion of procedural macros currently, so it was implemented as macro rules instead.