mod clone;
mod common_ord;
mod copy;
mod debug;
mod default;
mod eq;
mod hash;
mod ord;
mod partial_eq;
mod partial_ord;
#[cfg(feature = "zeroize")]
mod zeroize;
#[cfg(feature = "zeroize")]
mod zeroize_on_drop;
use proc_macro2::{Span, TokenStream};
use syn::{punctuated::Punctuated, spanned::Spanned, Meta, Path, Result, Token, TypeParamBound};
use crate::{Data, DeriveTrait, Error, Item};
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum Trait {
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
#[cfg(feature = "zeroize")]
Zeroize,
#[cfg(feature = "zeroize")]
ZeroizeOnDrop,
}
impl Trait {
fn implementation(&self) -> &dyn TraitImpl {
match self {
Trait::Clone => &clone::Clone,
Trait::Copy => ©::Copy,
Trait::Debug => &debug::Debug,
Trait::Default => &default::Default,
Trait::Eq => &eq::Eq,
Trait::Hash => &hash::Hash,
Trait::Ord => &ord::Ord,
Trait::PartialEq => &partial_eq::PartialEq,
Trait::PartialOrd => &partial_ord::PartialOrd,
#[cfg(feature = "zeroize")]
Trait::Zeroize => &zeroize::Zeroize,
#[cfg(feature = "zeroize")]
Trait::ZeroizeOnDrop => &zeroize_on_drop::ZeroizeOnDrop,
}
}
pub fn from_path(path: &Path) -> Result<Self> {
if let Some(ident) = path.get_ident() {
use Trait::*;
match ident.to_string().as_str() {
"Clone" => Ok(Clone),
"Copy" => Ok(Copy),
"Debug" => Ok(Debug),
"Default" => Ok(Default),
"Eq" => Ok(Eq),
"Hash" => Ok(Hash),
"Ord" => Ok(Ord),
"PartialEq" => Ok(PartialEq),
"PartialOrd" => Ok(PartialOrd),
#[cfg(feature = "zeroize")]
"Zeroize" => Ok(Zeroize),
#[cfg(feature = "zeroize")]
"ZeroizeOnDrop" => Ok(ZeroizeOnDrop),
"crate" => Err(Error::crate_(path.span())),
_ => Err(Error::trait_(path.span())),
}
} else {
Err(Error::trait_(path.span()))
}
}
}
impl TraitImpl for Trait {
fn as_str(&self) -> &'static str {
self.implementation().as_str()
}
fn default_derive_trait(&self) -> DeriveTrait {
self.implementation().default_derive_trait()
}
fn parse_derive_trait(
&self,
span: Span,
list: Punctuated<Meta, Token![,]>,
) -> Result<DeriveTrait> {
self.implementation().parse_derive_trait(span, list)
}
fn supports_union(&self) -> bool {
self.implementation().supports_union()
}
fn additional_where_bounds(&self, data: &Item) -> Option<TypeParamBound> {
self.implementation().additional_where_bounds(data)
}
fn additional_impl(&self, trait_: &DeriveTrait) -> Option<(Path, TokenStream)> {
self.implementation().additional_impl(trait_)
}
fn impl_path(&self, trait_: &DeriveTrait) -> Path {
self.implementation().impl_path(trait_)
}
fn build_signature(
&self,
item: &Item,
traits: &[DeriveTrait],
trait_: &DeriveTrait,
body: &TokenStream,
) -> TokenStream {
self.implementation()
.build_signature(item, traits, trait_, body)
}
fn build_body(&self, traits: &[DeriveTrait], trait_: &DeriveTrait, data: &Data) -> TokenStream {
self.implementation().build_body(traits, trait_, data)
}
}
pub trait TraitImpl {
fn as_str(&self) -> &'static str;
fn default_derive_trait(&self) -> DeriveTrait;
fn parse_derive_trait(
&self,
span: Span,
_list: Punctuated<Meta, Token![,]>,
) -> Result<DeriveTrait> {
Err(Error::options(span, self.as_str()))
}
fn supports_union(&self) -> bool {
false
}
fn additional_where_bounds(&self, _data: &Item) -> Option<TypeParamBound> {
None
}
fn additional_impl(&self, _trait_: &DeriveTrait) -> Option<(Path, TokenStream)> {
None
}
fn impl_path(&self, trait_: &DeriveTrait) -> Path {
trait_.path()
}
fn build_signature(
&self,
_item: &Item,
_traits: &[DeriveTrait],
_trait_: &DeriveTrait,
_body: &TokenStream,
) -> TokenStream {
TokenStream::new()
}
fn build_body(
&self,
_traits: &[DeriveTrait],
_trait_: &DeriveTrait,
_data: &Data,
) -> TokenStream {
TokenStream::new()
}
}