[][src]Attribute Macro inert_derive::neutralize

#[neutralize]

Derives neutralizing traits.

There are two ways to use this procedural macro attribute.

#[inert::neutralize(as Self)]

Implements NeutralizeUnsafe with type Output = Self;. Given that this can type check if and only if Self is Sync, the traits Neutralize and NeutralizeMut are also automatically implemented.

#[inert::neutralize(as vis? unsafe InertFoo)]

Implements NeutralizeUnsafe with type Output = InertFoo;. InertFoo is a wrapper generated by the macro itself, its visibility is controlled by vis. A getter method named is generated for each field adorned with #[inert::field(vis? ident?)], if ident is missing, the getter is given the same name as the field itself.

Given the following Node type:

This example is not tested
#[inert::neutralize(as pub(crate) unsafe InertNode)]
struct Node {
    #[inert::field(pub(crate) tag)]
    name: String,
    #[inert::field(pub(crate))]
    attributes: Vec<Attribute>,
    #[inert::field]
    children: RefCell<Vec<Node>>,
}

The following code will be generated:

This example is not tested
pub(crate) struct InertNode {
    value: inert::Neutralized<Node>,
}

unsafe impl NeutralizeUnsafe for Node {
    type Output = InertNode;

    unsafe fn neutralize_unsafe(&self) -> &InertNode {
        &*(self as *const Self as *const Self::Output)
    }
}

impl InertNode {
    pub(crate) fn tag(&self) -> &Inert<String> {
        unsafe { Inert::new_unchecked(&self.name) }
    }

    pub(crate) fn attributes(&self) -> &Inert<Vec<Attribute>> {
        unsafe { Inert::new_unchecked(&self.attributes) }
    }

    fn children(&self) -> &Inert<RefCell<Vec<Node>>> {
        unsafe { Inert::new_unchecked(&self.children) }
    }
}