6 releases
Uses old Rust 2015
0.1.7 | Nov 21, 2016 |
---|---|
0.1.5 | Mar 30, 2016 |
0.1.4 | Jan 18, 2016 |
0.1.2 | Sep 16, 2015 |
0.1.1 | Aug 16, 2015 |
#575 in Rust patterns
213,567 downloads per month
Used in 505 crates
(34 directly)
15KB
270 lines
custom_derive!
Note: This crate has been superseded by macro-attr
.
This crate provides a macro that enables the use of custom derive
attributes.
Links
License
Licensed under either of
- MIT license (see LICENSE or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (see LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.
lib.rs
:
Note: This crate has been superseded by macro-attr
.
This crate provides a macro that enables the use of custom derive
attributes.
To use it, make sure you link to the crate like so:
#[macro_use] extern crate custom_derive;
<style type="text/css"> .link-block { font-family: "Fira Sans"; } .link-block > p { display: inline-block; } .link-block > p > strong { font-weight: 500; margin-right: 1em; } .link-block > ul { display: inline-block; padding: 0; list-style: none; } .link-block > ul > li { font-size: 0.8em; background-color: #eee; border: 1px solid #ccc; padding: 0.3em; display: inline-block; } </style>Note: the
custom_derive!
macro itself is not documented, as the automatic documentation for it would be uselessly huge and incomprehensible.
Usage
The macro should be used to wrap an entire single enum
or struct
declaration, including its attributes (both derive
and others). All derivation attributes which the macro does not recognise will be assumed to be custom, and treated accordingly.
custom_derive!
assumes that custom derivations are implemented as macros (of the same name). For example, here is a simple derivation macro:
#[macro_use] extern crate custom_derive;
trait TypeName {
fn type_name() -> &'static str;
}
trait ReprType {
type Repr;
}
macro_rules! TypeName {
(() $(pub)* enum $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };
(() $(pub)* struct $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };
(@impl $name:ident) => {
impl TypeName for $name {
fn type_name() -> &'static str { stringify!($name) }
}
};
}
macro_rules! TryFrom {
(($repr:ty) $(pub)* enum $name:ident $($tail:tt)*) => {
impl ReprType for $name {
type Repr = $repr;
}
};
}
custom_derive! {
#[allow(dead_code)]
#[repr(u8)]
#[derive(Clone, Copy, Debug, TryFrom(u8), TypeName)]
enum Foo { A, B }
}
fn main() {
let foo = Foo::B;
let v = foo as <Foo as ReprType>::Repr;
let msg = format!("{}: {:?} ({:?})", Foo::type_name(), foo, v);
assert_eq!(msg, "Foo: B (1)");
}
First, note that custom_derive!
passes any arguments on the derivation attribute to the macro. In the case of attributes without any arguments, ()
is passed instead.
Secondly, the macro is passed the entire item, sans attributes. It is the derivation macro's job to parse the item correctly.
Third, each derivation macro is expected to result in zero or more items, not including the item itself. As a result, it is not possible to mutate the item in any way, or attach additional attributes to it.
Finally, @impl
is merely a trick to pack multiple, different functions into a single macro. The sequence has no special meaning; it is simply distinct from the usual invocation syntax.