[][src]Derive Macro shorthand::ShortHand

#[derive(ShortHand)]
{
    // Attributes available to this derive:
    #[shorthand]
}

A proc_macro to derive getter, mutgetter and setter for fields.

A list of all attributes can be found here.

Attributes

option_as_ref

This attribute makes the getter return Option<&T> instead of &Option<T>. This feature is enabled by default and recommended, because most of the functions for Option consume the type.

You can find a discussion, about wether or not you should use it here.

const_fn

There is a new feature coming to rust called constant functions. Functions, that are marked with const can be executed by the compiler at compile time, if the value is known.

const fn add(value: usize, other: usize) -> usize { value + other }

let three = add(1, 2);

will be optimized to

let three = 3; 

Another benefit is, that you can also save the result in a const variable.

const fn add(value: usize, other: usize) -> usize { value + other }

const THREE: usize = add(1, 2);

This feature is currently work in progress see rust-lang/rust#57563

You can read more about it here or in the RFC.

By enabling this feature the derived functions will be const.

Please note, that not everything is currently supported and therefore some attributes will ignore this attribute and not add const to the function.

primitive_copy

This attribute will cause get functions to return a copy of the type, instead of a reference.

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
#[shorthand(disable(primitive_copy))]
struct Example {
    field: usize,
    #[shorthand(enable(primitive_copy))]
    other: usize,
}

let example = Example::default();

assert_eq!(example.field(), &0);
assert_eq!(example.other(), 0);

This attribute is enabled by default.

Please note, that this does only work with primitive types from the standard library, other types have to be marked with copy.

copy

There is no way for a proc_macro to know wether or not a type implements Copy, so fields, where the getter should return a copy, instead of a reference have to be marked with #[shorthand(copy)].

use shorthand::ShortHand;

#[derive(Default, Copy, Clone, PartialEq, Debug)]
struct Number(pub usize);

#[derive(ShortHand, Default)]
struct Example {
    #[shorthand(enable(copy))]
    field: Number,
    other: Number,
}

let example = Example::default();

assert_eq!(example.field(), Number(0));
assert_eq!(example.other(), &Number(0));

inline

This attribute adds #[inline(always)] to the derived function.

#[inline(always)]
fn add(a: usize, b: usize) -> usize { a + b }

let three = add(1, 2);

will be optimized to

let three = 1 + 2; 

You can read more about the inline attribute here.

A discussion, about wether or not you should use it: https://internals.rust-lang.org/t/when-should-i-use-inline/598

This attribute is enabled by default.

must_use

This attribute will mark functions with #[must_use], which means, that their results have to be used, otherwise you get a warning

#[must_use]
fn hello() -> &'static str { "hello" }

hello();
warning: unused return value of `hello` that must be used
 --> src/main.rs:6:5
  |
6 |     hello();
  |     ^^^^^^^^
  |
  = note: `#[warn(unused_must_use)]` on by default

This is disabled by default and can only be enabled for getter and mutable getter. If you really need this attributes on a setter you can just mark the field with #[must_use] and shorthand will automatically forward the attribute (see here).

get

This attribute derives a function, to get the value of a field (sometimes referred to as getter).

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
#[shorthand(disable(get))]
struct Example {
    #[shorthand(enable(get))]
    field: usize,
}

let example = Example::default();

assert_eq!(example.field(), 0);

This attribute is enabled by default.

set

This attribute derives a function, to set the value of a field (sometimes referred to as setter).

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
#[shorthand(disable(get, set))]
struct Example {
    #[shorthand(enable(get, set))]
    field: usize,
}

let mut example = Example::default();

example.set_field(1);

assert_eq!(example.field(), 1);

This attribute is enabled by default.

ignore_phantomdata

Like the name implies, this will tell the proc_macro, to ignore PhantomData and to not generate functions for it.

This example deliberately fails to compile
use core::marker::PhantomData;
use shorthand::ShortHand;

#[derive(ShortHand, Default)]
struct Example {
    field: PhantomData<usize>,
}

let example = Example::default();
example.field(); // this will cause a compiler error, because the function does not exist!

This feature is enabled by default.

skip

Like the name implies, this will tell the proc_macro to not generate functions for this field (skipping it).

This example deliberately fails to compile
use shorthand::ShortHand;

#[derive(ShortHand, Default)]
struct Example {
    #[shorthand(enable(skip))]
    field: usize,
}

let example = Example::default();
example.field(); // this will cause a compiler error, because the function does not exist!

into

The into attribute adds VALUE: Into<field_type> as a trait bound for setters (Into).

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
struct Example {
    #[shorthand(enable(into))]
    field: String,
    other: String,
}

let mut example = Example::default();

example.set_field("field"); // accepts any type, that implements Into<String> or From<String>
example.set_other("other".to_string());

assert_eq!(example.field(), &"field".to_string());
assert_eq!(example.other(), &"other".to_string());

This struct uses VALUE as a generic, so you should NOT use that on your struct

struct DoNotDoThis<VALUE> {
    value: VALUE,
}

This attribute is not enabled by default.

forward

The forward attribute, allows you to control how attributes are forwarded. By default the proc_macro will forward the following attributes of the field to the generated function:

use shorthand::ShortHand;

#[derive(ShortHand)]
#[shorthand(disable(forward))]
struct Example {
    #[shorthand(enable(forward(must_use)))]
    #[must_use]
    hello: &'static str,
}

The hello function would now have a #[must_use] attribute:

#[must_use]
fn hello() -> &'static str { "hello" }

This attribute can be applied multiple times on the same field, which would allow controlled forwarding. Please note, that this feature does not work, until this issue is fixed https://github.com/rust-lang/rust/issues/67839.

use shorthand::ShortHand;

#[derive(ShortHand)]
struct Example {
    #[shorthand(enable(forward))]
    #[must_use]
    #[shorthand(disable(forward))]
    #[allow(dead_code)]
    hello: &'static str,
}

In this example only #[must_use] is forwarded and #[allow(dead_code)] is not.

This attribute can also be used to forward parts of docs. A doc comment /// will be converted to #[doc] attribute.

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
struct Example {
    /// Data has some special restrictions.
    /// - The String can only exist of uppercase characters
    /// - Numbers are allowed
    /// - The String has a maximum size of 5.
    #[shorthand(disable(forward))]
    /// This part will not be forwarded.
    #[shorthand(enable(forward))]
    ///
    /// # Example
    ///
    /// ```
    /// println!("nice");
    /// ```
    data: String,
}

will instruct shorthand to generate the following code

impl Example {
    /// Data has some special restrictions.
    /// - The String can only exist of uppercase characters
    /// - Numbers are allowed
    /// - The String has a maximum size of 5.
    ///
    /// # Example
    ///
    /// ```
    /// println!("nice");
    /// ```
    #[inline(always)]
    pub fn data(&self) -> &String { &self.data }

    /// Data has some special restrictions.
    /// - The String can only exist of uppercase characters
    /// - Numbers are allowed
    /// - The String has a maximum size of 5.
    ///
    /// # Example
    ///
    /// ```
    /// println!("nice");
    /// ```
    #[inline(always)]
    pub fn set_data(&mut self, value: String) -> &mut Self {
        self.data = value;
        self
    }
}

as you can see the line /// This part will not be forwarded. did not get forwarded.

ignore_underscore

This attribute instructs the proc_macro to ignore fields prefixed with an _.

This attribute is not enabled by default.

collection_magic

This attribute instructs the proc_macro to derive additonal functions for fields, that have a collection.

The following collections are supported:

It will derive a push_field function for Vec and for all the other collection types an insert_field function.

use shorthand::ShortHand;
use std::collections::BTreeMap;

#[derive(ShortHand, Default)]
struct Example {
    #[shorthand(enable(collection_magic))]
    value: Vec<usize>,
    #[shorthand(enable(collection_magic))]
    other: BTreeMap<usize, usize>,
}

let mut example = Example::default();

example.push_value(1);
example.push_value(2);
example.push_value(3);

assert_eq!(example.value(), &vec![1, 2, 3]);

example.insert_other(1, 1);
example.insert_other(2, 2);
example.insert_other(3, 3);

assert_eq!(example.other(), &{
    let mut result = BTreeMap::new();
    result.insert(1, 1);
    result.insert(2, 2);
    result.insert(3, 3);
    result
});

strip_option

This will change the input type for setter of optional fields from Option<T> to T.

use shorthand::ShortHand;

#[derive(ShortHand, Default)]
struct Example {
    value: Option<usize>,
    #[shorthand(enable(strip_option))]
    other: Option<usize>,
}

Example::default().set_value(Some(0));
Example::default().set_other(0);

This attribute is diabled by default.

clone

The getter will clone the field instead of returning a reference.

use shorthand::ShortHand;
use std::rc::Rc;

#[derive(ShortHand, Default)]
struct Example {
    #[shorthand(enable(clone))]
    value: Rc<usize>,
}

assert_eq!(Example::default().value(), Rc::new(0));

This attribute is diabled by default.