Macro sophia_iri::wrap

source ·
macro_rules! wrap {
    ($wid:ident<$tid:ident: $bound:path>: $new:item $($item:item)*) => { ... };
    ($wid:ident borrowing $bid:ty: $new:item $($item:item)*) => { ... };
}
Expand description

This macro is used to create a read-only wrapper around a type T, usually for the purpose of guaranteeing that the wrapped value verifies some condition. This macro takes care of defining all the usual traits for the wrapper type.

In its most general form, it is used like this:

wrap! { MyWrapper<T: SomeTrait> :
    // NB: the trait bound is required, as well as the trailing colon (':').

    // You can include members in the impl of the wrapper type.
    // At the very least, you must define a `new` constructor,
    // that will check the appropriate condition on the wrapped value,
    // and return a `Result`.

    /// The `new` constructor should carry the documentation of the type;
    /// since the generated documentation for the type will point to it.
    pub fn new(inner: T) -> Result<Self, SomeError> {
        if inner.check_some_property() {
            Ok(Self(inner))
        } else {
            Err(SomeError {})
        }
    }
}

A more specific form is when the trait that T must satisfy is std::borrow::Borrow<U>, in which case more traits can be implemented by the wrapper. This is achieved with the following syntax:

wrap! { Foo borrowing str :
    /// As before
    pub fn new(inner: T) -> Result<Self, String> {
        if inner.borrow().contains("foo") {
            Ok(Self(inner))
        } else {
            Err(format!("{:?} is not a valid Foo", inner.borrow()))
        }
    }
}

Two examples are availble, illustrating the members and trait implementation generated by this macro.

NB: the documentation of the wrapper will point to the documentation of the new method.