blob: e4fe60e682bfb7c2d5a12955863b425f16c9290f [file] [log] [blame] [edit]
//! This library provides two derive macros. One, `Getters` for autogenerating getters and
//! `Dissolve` for consuming a struct returning a tuple of all fields. They can only be
//! used on named structs.
//!
//! # Derives
//!
//! Only named structs can derive `Getters` or `Dissolve`.
//!
//! # `Getter` methods generated
//!
//! The getter methods generated shall bear the same name as the struct fields and be
//! publicly visible. The methods return an immutable reference to the struct field of the
//! same name. If there is already a method defined with that name there'll be a collision.
//! In these cases one of two attributes can be set to either `skip` or `rename` the getter.
//!
//!
//! # `Getters` Usage
//!
//! In lib.rs or main.rs;
//!
//! ```edition2018
//! use derive_getters::Getters;
//!
//! #[derive(Getters)]
//! struct Number {
//! num: u64,
//! }
//!
//! fn main() {
//! let number = Number { num: 655 };
//! assert!(number.num() == &655);
//! }
//! ```
//!
//! Here, a method called `num()` has been created for the `Number` struct which gives a
//! reference to the `num` field.
//!
//! This macro can also derive on structs that have simple generic types. For example;
//!
//! ```edition2018
//! # use derive_getters::Getters;
//! #[derive(Getters)]
//! struct Generic<T, U> {
//! gen_t: T,
//! gen_u: U,
//! }
//! #
//! # fn main() { }
//! ```
//!
//! The macro can also handle generic types with trait bounds. For example;
//! ```edition2018
//! # use derive_getters::Getters;
//! #[derive(Getters)]
//! struct Generic<T: Clone, U: Copy> {
//! gen_t: T,
//! gen_u: U,
//! }
//! #
//! # fn main() { }
//! ```
//! The trait bounds can also be declared in a `where` clause.
//!
//! Additionaly, simple lifetimes are OK too;
//! ```edition2018
//! # use derive_getters::Getters;
//! #[derive(Getters)]
//! struct Annotated<'a, 'b, T> {
//! stuff: &'a T,
//! comp: &'b str,
//! num: u64,
//! }
//! #
//! # fn main() { }
//! ```
//!
//! # `Getter` Attributes
//! Getters can be further configured to either skip or rename a getter.
//!
//! * #[getter(skip)]
//! Will skip generating a getter for the field being decorated.
//!
//! * #[getter(rename = "name")]
//! Changes the name of the getter (default is the field name) to "name".
//!
//!```edition2018
//! # use derive_getters::Getters;
//! #[derive(Getters)]
//! struct Attributed {
//! keep_me: u64,
//!
//! #[getter(skip)]
//! skip_me: u64,
//!
//! #[getter(rename = "number")]
//! rename_me: u64,
//! }
//! #
//! # fn main() { }
//! ```
//!
//! # `Dissolve` method generated
//!
//! Deriving `Dissolve` on a named struct will generate a method `dissolve(self)` which
//! shall return a tuple of all struct fields in the order they were defined. Calling this
//! method consumes the struct. The name of this method can be changed with an attribute.
//!
//! # `Dissolve` usage
//!
//! ```edition2018
//! # use derive_getters::Dissolve;
//! #[derive(Dissolve)]
//! struct Stuff {
//! name: String,
//! price: f64,
//! count: usize,
//! }
//!
//! fn main() {
//! let stuff = Stuff {
//! name: "Hogie".to_owned(),
//! price: 123.4f64,
//! count: 100,
//! };
//!
//! let (n, p, c) = stuff.dissolve();
//! assert!(n == "Hogie");
//! assert!(p == 123.4f64);
//! assert!(c == 100);
//! }
//! ```
//!
//! # `Dissolve` Attributes
//! You can rename the `dissolve` function by using a struct attribute.
//!
//! * #[dissolve(rename = "name")]
//!
//! ```edition2018
//! # use derive_getters::Dissolve;
//! #[derive(Dissolve)]
//! #[dissolve(rename = "shatter")]
//! struct Numbers {
//! a: u64,
//! b: i64,
//! c: f64,
//! }
//! #
//! # fn main() { }
//! ```
//!
//! # Panics
//!
//! If `Getters` or `Dissolve` are derived on unit or unnamed structs, enums or unions.
//!
//! # Cannot Do
//! Const generics aren't handled by this macro nor are they tested.
use std::convert::TryFrom;
extern crate proc_macro;
use syn::{DeriveInput, parse_macro_input};
mod faultmsg;
mod dissolve;
mod getters;
mod extract;
/// Generate getter methods for all named struct fields in a seperate struct `impl` block.
/// Getter methods share the name of the field they're 'getting'. Methods return an
/// immutable reference to the field.
#[proc_macro_derive(Getters, attributes(getter))]
pub fn getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
getters::NamedStruct::try_from(&ast)
.map(|ns| ns.emit())
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
/// Produce a `dissolve` method that consumes the named struct returning a tuple of all the
/// the struct fields.
#[proc_macro_derive(Dissolve, attributes(dissolve))]
pub fn dissolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
dissolve::NamedStruct::try_from(&ast)
.map(|ns| ns.emit())
.unwrap_or_else(|err| err.to_compile_error())
.into()
}