This crate provides a set of alternative #[derive]
attributes for Rust.
derivative uses attributes to make it possible to derive more implementations
than the built-in derive(Trait)
. Here are a few examples of stuffs you cannot
just derive
.
You can derive Default
on enumerations:
With derivative
Original
#![allow(unused)]
fn main() {
extern crate derivative;
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Default(bound=""))]
pub enum Option<T> {
#[derivative(Default)]
/// No value
None,
/// Some value `T`
Some(T),
}
}
#![allow(unused)]
fn main() {
#![no_implicit_prelude]
extern crate core;
use core::default::Default;
use Option::None;
pub enum Option<T> {
/// No value
None,
/// Some value `T`
Some(T),
}
impl<T> Default for Option<T> {
/// Returns None.
#[inline]
fn default() -> Option<T> {
None
}
}
}
You can use different default values for some fields:
With derivative
Original
#![allow(unused)]
fn main() {
extern crate derivative;
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Default)]
pub struct RegexOptions {
pub pats: Vec<String>,
#[derivative(Default(value="10 * (1 << 20)"))]
pub size_limit: usize,
#[derivative(Default(value="2 * (1 << 20)"))]
pub dfa_size_limit: usize,
pub case_insensitive: bool,
pub multi_line: bool,
pub dot_matches_new_line: bool,
pub swap_greed: bool,
pub ignore_whitespace: bool,
#[derivative(Default(value="true"))]
pub unicode: bool,
}
}
#![allow(unused)]
fn main() {
pub struct RegexOptions {
pub pats: Vec<String>,
pub size_limit: usize,
pub dfa_size_limit: usize,
pub case_insensitive: bool,
pub multi_line: bool,
pub dot_matches_new_line: bool,
pub swap_greed: bool,
pub ignore_whitespace: bool,
pub unicode: bool,
}
impl Default for RegexOptions {
fn default() -> Self {
RegexOptions {
pats: vec![],
size_limit: 10 * (1 << 20),
dfa_size_limit: 2 * (1 << 20),
case_insensitive: false,
multi_line: false,
dot_matches_new_line: false,
swap_greed: false,
ignore_whitespace: false,
unicode: true,
}
}
}
}
Want a transparent Debug
implementation for your wrapper? We got that:
With derivative
Original
#![allow(unused)]
fn main() {
extern crate derivative;
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Debug="transparent")]
pub struct Wrapping<T>(pub T);
}
#![allow(unused)]
fn main() {
use std::fmt;
pub struct Wrapping<T>(pub T);
impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
}
Need to ignore a field? We got that too:
With derivative
Original
#![allow(unused)]
fn main() {
extern crate derivative;
use derivative::Derivative;
#[derive(PartialEq, Hash)]
struct Identifier;
#[derive(Derivative)]
#[derivative(PartialEq, Hash)]
pub struct Version {
/// The major version.
pub major: u64,
/// The minor version.
pub minor: u64,
/// The patch version.
pub patch: u64,
/// The pre-release version identifier.
pub pre: Vec<Identifier>,
// We should ignore build metadata
// here, otherwise versions v1 and
// v2 can exist such that !(v1 < v2)
// && !(v1 > v2) && v1 != v2, which
// violate strict total ordering rules.
#[derivative(PartialEq="ignore")]
#[derivative(Hash="ignore")]
/// The build metadata, ignored when
/// determining version precedence.
pub build: Vec<Identifier>,
}
}
#![allow(unused)]
fn main() {
use std::{cmp, hash};
#[derive(PartialEq, Hash)]
struct Identifier;
pub struct Version {
/// The major version.
pub major: u64,
/// The minor version.
pub minor: u64,
/// The patch version.
pub patch: u64,
/// The pre-release version identifier.
pub pre: Vec<Identifier>,
/// The build metadata, ignored when
/// determining version precedence.
pub build: Vec<Identifier>,
}
impl cmp::PartialEq for Version {
#[inline]
fn eq(&self, other: &Version) -> bool {
// We should ignore build metadata
// here, otherwise versions v1 and
// v2 can exist such that !(v1 < v2)
// && !(v1 > v2) && v1 != v2, which
// violate strict total ordering rules.
self.major == other.major &&
self.minor == other.minor &&
self.patch == other.patch &&
self.pre == other.pre
}
}
impl hash::Hash for Version {
fn hash<H: hash::Hasher>(&self, into: &mut H) {
self.major.hash(into);
self.minor.hash(into);
self.patch.hash(into);
self.pre.hash(into);
}
}
}