Derive Macro amplify::Wrapper

source ·
#[derive(Wrapper)]
{
    // Attributes available to this derive:
    #[wrap]
    #[wrapper]
    #[amplify_crate]
}
Expand description

Creates rust new type wrapping existing type. Can be used in structures containing multiple named or unnamed fields; in this case the field you’d like to wrap should be marked with #[wrap] attribute; otherwise the first field is assumed to be the wrapped one.

NB: You have to use derive(From) in order foe Wrapper to work properly. Also, in case of multiple fields, each non-wrapped field type must implement Default trait.

Supports automatic implementation of the following traits:

  • amplify::Wrapper
  • [AsRef]
  • [core::borrow::Borrow] You may skip AsRef and Borrow implementations with #[wrapper(NoRefs)].

You can implement additional derives, it they are implemented for the wrapped type, using #[wrapper()] proc macro:

  1. Reference access to the inner type:
    • Deref for implementing [core::ops::Deref]
    • AsSlice for implementing [AsRef]<[u8]>
    • BorrowSlice for implementing [core::borrow::Borrow]<[Self::Inner]>
  2. Formatting:
    • FromStr for implementing [core::str::FromStr]
    • Debug for implementing [core::fmt::Debug]
    • Display for implementing [core::fmt::Display]
    • FromHex for implementing [amplify::hex::FromHex]
    • LowerHex for implementing [core::fmt::LowerHex]
    • UpperHex for implementing [core::fmt::UpperHex]
    • LowerExp for implementing [core::fmt::LowerExp]
    • UpperExp for implementing [core::fmt::UpperExp]
    • Octal for implementing [core::fmt::Octal]
  3. Indexed access to the inner type:
    • Index for implementing [core::ops::Index]<usize>
    • IndexRange for implementing [core::ops::Index]<[core::ops::Range]<usize>>
    • IndexTo for implementing [core::ops::Index]<[core::ops::RangeTo]<usize>>
    • IndexFrom for implementing [core::ops::Index]<[core::ops::RangeFrom]<usize>>
    • IndexInclusive for implementing [core::ops::Index]<[core::ops::RangeInclusive]<usize>>
    • IndexToInclusive for implementing [core::ops::Index]<[core::ops::RangeToInclusive]<usize>>
    • IndexFull for implementing [core::ops::Index]<[core::ops::RangeFrom]<usize>>
  4. Arithmetic operations:
    • Neg for implementing [core::ops::Neg]
    • Add for implementing [core::ops::Add]
    • Sub for implementing [core::ops::Sub]
    • Mul for implementing [core::ops::Mul]
    • Div for implementing [core::ops::Div]
    • Rem for implementing [core::ops::Rem]
  5. Boolean and bit-wise operations:
    • Not for implementing [core::ops::Not]
    • BitAnd for implementing [core::ops::BitAnd]
    • BitOr for implementing [core::ops::BitOr]
    • BitXor for implementing [core::ops::BitXor]
    • Shl for implementing [core::ops::Shl]
    • Shr for implementing [core::ops::Shr]

There are shortcuts for derivations:

  • #[wrapper(Hex)] will derive both LowerHex, UpperHex and FromHex;
  • #[wrapper(Exp)] will derive both LowerExp and UpperExp;
  • #[wrapper(NumberFmt)] will derive all number formatting traits (LowerHex, UpperHex, LowerExp, UpperExp, Octal);
  • #[wrapper(RangeOps)] will derive all index traits working with ranges (IndexRange, IndexTo, IndexFrom, IndexInclusive, IndexToInclusive, IndexFull);
  • #[wrapper(MathOps)] will derive all arithmetic operations (Neg, Add, Sub, Mul, Div, Rem);
  • #[wrapper(BoolOps)] will derive all boolean operations (Not, BitAnd, BitOr, BitXor);
  • #[wrapper(BitOps)] will derive all boolean operations and bit shifts (Not, BitAnd, BitOr, BitXor, Shl, Shr).

Other traits, such as [PartialEq], [Eq], [PartialOrd], [Ord], [Hash] can be implemented using standard #[derive] attribute in the same manner as [Default], [Debug] and From

§Example

Simple wrapper:

use amplify::Wrapper;

#[derive(Wrapper, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, From, Debug, Display)]
#[display(inner)]
#[wrapper(LowerHex, UpperHex, Octal)]
#[wrapper(MathOps, BitOps)]
struct Int64(i64);

More complex wrapper with multiple unnamed fields:

use std::marker::PhantomData;

use amplify::Wrapper;

#[derive(Clone, Wrapper, Default, From)]
#[wrapper(Debug)]
struct Wrapped<T, U>(
    #[wrap]
    #[from]
    HashMap<usize, Vec<U>>,
    PhantomData<T>,
)
where U: Sized + Clone + Debug;

let w = Wrapped::<(), u8>::default();
assert_eq!(w.into_inner(), HashMap::<usize, Vec<u8>>::default());

Wrappers for indexable types

use amplify::Wrapper;

#[derive(Wrapper, From)]
#[wrapper(Index, RangeOps)]
struct VecNewtype(Vec<u8>);