]> git.lizzy.rs Git - enumset.git/blobdiff - enumset_derive/src/lib.rs
Suppress certain clippy warnings. Fixes #28.
[enumset.git] / enumset_derive / src / lib.rs
index bc479496ae7ba5c4a7947477c77b5794cbcd6f94..993ccc071af965edfb2bfdbff0b37019dc8b4f96 100644 (file)
@@ -20,6 +20,7 @@ fn error<T>(span: Span, message: &str) -> Result<T> {
 #[darling(attributes(enumset), default)]
 struct EnumsetAttrs {
     no_ops: bool,
+    no_super_impls: bool,
     serialize_as_list: bool,
     serialize_deny_unknown: bool,
     #[darling(default)]
@@ -63,6 +64,8 @@ struct EnumSetInfo {
 
     /// Avoid generating operator overloads on the enum type.
     no_ops: bool,
+    /// Avoid generating implementations for `Clone`, `Copy`, `Eq`, and `PartialEq`.
+    no_super_impls: bool,
     /// Serialize the enum as a list.
     serialize_as_list: bool,
     /// Disallow unknown bits while deserializing the enum.
@@ -82,6 +85,7 @@ impl EnumSetInfo {
             used_variant_names: HashSet::new(),
             used_discriminants: HashSet::new(),
             no_ops: attrs.no_ops,
+            no_super_impls: attrs.no_super_impls,
             serialize_as_list: attrs.serialize_as_list,
             serialize_deny_unknown: attrs.serialize_deny_unknown
         }
@@ -350,7 +354,7 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream {
             fn serialize<S: #serde::Serializer>(
                 set: #enumset::EnumSet<#name>, ser: S,
             ) -> #core::result::Result<S::Ok, S::Error> {
-                #serde::Serialize::serialize(&(set.__enumset_underlying as #serialize_repr), ser)
+                #serde::Serialize::serialize(&(set.__priv_repr as #serialize_repr), ser)
             }
             fn deserialize<'de, D: #serde::Deserializer<'de>>(
                 de: D,
@@ -358,7 +362,7 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream {
                 let value = <#serialize_repr as #serde::Deserialize>::deserialize(de)?;
                 #check_unknown
                 #core::prelude::v1::Ok(#enumset::EnumSet {
-                    __enumset_underlying: (value & #all_variants) as #repr,
+                    __priv_repr: (value & #all_variants) as #repr,
                 })
             }
         }
@@ -431,6 +435,33 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream {
         quote!((*self as u32) == (*other as u32))
     };
 
+    // used in the enum_set! macro `const fn`s.
+    let self_as_repr_mask = if is_uninhabited {
+        quote! { 0 } // impossible anyway
+    } else {
+        quote! { 1 << self as #repr }
+    };
+
+    let super_impls = if info.no_super_impls {
+        quote! {}
+    } else {
+        quote! {
+            impl #core::cmp::PartialEq for #name {
+                fn eq(&self, other: &Self) -> bool {
+                    #eq_impl
+                }
+            }
+            impl #core::cmp::Eq for #name { }
+            #[allow(clippy::expl_impl_clone_on_copy)]
+            impl #core::clone::Clone for #name {
+                fn clone(&self) -> Self {
+                    *self
+                }
+            }
+            impl #core::marker::Copy for #name { }
+        }
+    };
+
     quote! {
         unsafe impl #enumset::__internal::EnumSetTypePrivate for #name {
             type Repr = #repr;
@@ -441,24 +472,34 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream {
 
         unsafe impl #enumset::EnumSetType for #name { }
 
-        impl #core::cmp::PartialEq for #name {
-            fn eq(&self, other: &Self) -> bool {
-                #eq_impl
+        #super_impls
+
+        impl #name {
+            /// Creates a new enumset with only this variant.
+            #[deprecated(note = "This method is an internal implementation detail generated by \
+                                 the `enumset` crate's procedural macro. It should not be used \
+                                 directly. Use `EnumSet::only` instead.")]
+            #[doc(hidden)]
+            pub const fn __impl_enumset_internal__const_only(self) -> #enumset::EnumSet<#name> {
+                #enumset::EnumSet { __priv_repr: #self_as_repr_mask }
             }
-        }
-        impl #core::cmp::Eq for #name { }
-        impl #core::clone::Clone for #name {
-            fn clone(&self) -> Self {
-                *self
+
+            /// Creates a new enumset with this variant added.
+            #[deprecated(note = "This method is an internal implementation detail generated by \
+                                 the `enumset` crate's procedural macro. It should not be used \
+                                 directly. Use the `|` operator instead.")]
+            #[doc(hidden)]
+            pub const fn __impl_enumset_internal__const_merge(
+                self, chain: #enumset::EnumSet<#name>,
+            ) -> #enumset::EnumSet<#name> {
+                #enumset::EnumSet { __priv_repr: chain.__priv_repr | #self_as_repr_mask }
             }
         }
-        impl #core::marker::Copy for #name { }
 
         #ops
     }
 }
 
-/// A wrapper that parses the input enum.
 #[proc_macro_derive(EnumSetType, attributes(enumset))]
 pub fn derive_enum_set_type(input: TokenStream) -> TokenStream {
     let input: DeriveInput = parse_macro_input!(input);