diff --git a/fixed-map-derive/src/any_variants.rs b/fixed-map-derive/src/any_variants.rs index c28a245..8e8b6c9 100644 --- a/fixed-map-derive/src/any_variants.rs +++ b/fixed-map-derive/src/any_variants.rs @@ -10,15 +10,15 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let ident = &cx.ast.ident; let lt = cx.lt; - let clone = &cx.toks.clone; - let copy = &cx.toks.copy; - let default = &cx.toks.default; - let eq = &cx.toks.eq; - let key_trait = &cx.toks.key_trait; - let mem = &cx.toks.mem; - let option = &cx.toks.option; - let partial_eq = &cx.toks.partial_eq; - let storage_trait = &cx.toks.storage_trait; + let clone_t = cx.toks.clone_t(); + let copy_t = cx.toks.copy_t(); + let default_t = cx.toks.default_t(); + let eq_t = cx.toks.eq_t(); + let key_t = cx.toks.key_t(); + let mem = cx.toks.mem(); + let option = cx.toks.option(); + let partial_eq_t = cx.toks.partial_eq_t(); + let storage_t = cx.toks.storage_t(); let const_wrapper = Ident::new( &format!("__IMPL_KEY_FOR_{}", cx.ast.ident), @@ -32,6 +32,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut field_inits = Vec::new(); let mut field_clones = Vec::new(); let mut field_partial_eqs = Vec::new(); + let mut field_partial_not_eqs = Vec::new(); let mut contains_key = Vec::new(); let mut get = Vec::new(); let mut get_mut = Vec::new(); @@ -46,14 +47,21 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let var = &variant.ident; let name = Ident::new(&format!("f{}", index), Span::call_site()); - field_inits.push(quote!(#name: #default::default())); - field_clones.push(quote!(#name: #clone::clone(&self.#name))); + field_inits.push(quote!(#name: #default_t::default())); + field_clones.push(quote!(#name: #clone_t::clone(&self.#name))); + field_partial_eqs.push(quote! { - if self.#name != other.#name { + if #partial_eq_t::ne(&self.#name, &other.#name) { return false; } }); + field_partial_not_eqs.push(quote! { + if #partial_eq_t::ne(&self.#name, &other.#name) { + return true; + } + }); + let kind = match &variant.fields { Fields::Unit => { len.push(quote!(usize::from(#option::is_some(&self.#name)))); @@ -67,7 +75,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result insert.push(quote!(#mem::replace(&mut self.#name, #option::Some(value)))); remove.push(quote!(#mem::replace(&mut self.#name, #option::None))); retain.push(quote! { - if let Some(val) = #option::as_mut(&mut self.#name) { + if let #option::Some(val) = #option::as_mut(&mut self.#name) { if !func(#ident::#var, val) { self.#name = None; } @@ -86,8 +94,8 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } let element = unnamed.unnamed.first().expect("Expected one element"); - let storage = quote!(<#element as #key_trait>::Storage::); - let as_storage = quote!(<#storage as #storage_trait<#element, V>>); + let storage = quote!(<#element as #key_t>::Storage::); + let as_storage = quote!(<#storage as #storage_t<#element, V>>); len.push(quote!(#as_storage::len(&self.#name))); is_empty.push(quote!(#as_storage::is_empty(&self.#name))); @@ -105,7 +113,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #as_storage::retain(&mut self.#name, |k, v| func(#ident::#var(k), v)); }); - copy_bounds.push(quote!(#storage: #copy)); + copy_bounds.push(quote!(#storage: #copy_t)); FieldKind::Complex { element: quote!(#element), @@ -131,7 +139,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let mut iter_clone = Vec::new(); for FieldSpec { name, .. } in &field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); } let pattern = &pattern; @@ -157,7 +165,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #clone for Storage where V: #clone { + impl #clone_t for Storage where V: #clone_t { #[inline] fn clone(&self) -> Storage { Storage { @@ -167,22 +175,28 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #copy for Storage where V: #copy, #(#copy_bounds,)* {} + impl #copy_t for Storage where V: #copy_t, #(#copy_bounds,)* {} #[automatically_derived] - impl #partial_eq for Storage where V: #partial_eq { + impl #partial_eq_t for Storage where V: #partial_eq_t { #[inline] fn eq(&self, other: &Storage) -> bool { #(#field_partial_eqs;)* true } + + #[inline] + fn ne(&self, other: &Storage) -> bool { + #(#field_partial_not_eqs;)* + false + } } #[automatically_derived] - impl #eq for Storage where V: #eq {} + impl #eq_t for Storage where V: #eq_t {} #[automatically_derived] - impl #default for Storage { + impl #default_t for Storage { #[inline] fn default() -> Self { Self { @@ -192,7 +206,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #storage_trait<#ident, V> for Storage { + impl #storage_t<#ident, V> for Storage { type Iter<#lt> = Iter<#lt, V> where V: #lt; type Keys<#lt> = Keys<#lt, V> where V: #lt; type Values<#lt> = Values<#lt, V> where V: #lt; @@ -314,7 +328,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #key_trait for #ident { + impl #key_t for #ident { type Storage = Storage; } @@ -339,9 +353,9 @@ fn build_iter_next( assoc_type: &Ident, lt: Option<&syn::Lifetime>, ) -> Result<(), ()> { - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let ident = &cx.ast.ident; for FieldSpec { @@ -417,13 +431,14 @@ fn build_iter_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; let ident = &cx.ast.ident; let vis = &cx.ast.vis; + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let clone_t = cx.toks.clone_t(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -441,7 +456,7 @@ fn build_iter_impl( )?; for FieldSpec { name, kind, .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -470,7 +485,7 @@ fn build_iter_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -514,15 +529,16 @@ fn build_keys_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; - let bool_type = &cx.toks.bool_type; - let mem = &cx.toks.mem; let ident = &cx.ast.ident; let vis = &cx.ast.vis; + let bool_type = cx.toks.bool_type(); + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let mem = cx.toks.mem(); + let option = cx.toks.option(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -539,7 +555,7 @@ fn build_keys_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -608,7 +624,7 @@ fn build_keys_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -652,12 +668,13 @@ fn build_values_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let clone = &cx.toks.clone; let vis = &cx.ast.vis; + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let option = cx.toks.option(); + let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -673,7 +690,7 @@ fn build_values_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -742,7 +759,7 @@ fn build_values_impl( } #[automatically_derived] - impl<#lt, V> #clone for #type_name<#lt, V> where V: #lt { + impl<#lt, V> #clone_t for #type_name<#lt, V> where V: #lt { #[inline] fn clone(&self) -> Self { Self { @@ -785,12 +802,13 @@ fn build_iter_mut_impl( ) -> Result<(TokenStream, Vec), ()> { let type_name = syn::Ident::new(id, Span::call_site()); - let lt = cx.lt; let ident = &cx.ast.ident; + let lt = cx.lt; let vis = &cx.ast.vis; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; - let option = &cx.toks.option; + + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); + let iterator_t = cx.toks.iterator_t(); + let option = cx.toks.option(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -871,11 +889,12 @@ fn build_values_mut_impl( let type_name = syn::Ident::new(id, Span::call_site()); let lt = cx.lt; - let option = &cx.toks.option; - let iterator_t = &cx.toks.iterator_t; - let clone = &cx.toks.clone; let vis = &cx.ast.vis; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + + let option = cx.toks.option(); + let iterator_t = cx.toks.iterator_t(); + let clone_t = cx.toks.clone_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -892,7 +911,7 @@ fn build_values_mut_impl( .. } in field_specs { - iter_clone.push(quote!(#name: #clone::clone(&self.#name))); + iter_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -994,10 +1013,11 @@ fn build_into_iter_impl( let ident = &cx.ast.ident; let vis = &cx.ast.vis; - let option = &cx.toks.option; - let clone = &cx.toks.clone; - let iterator_t = &cx.toks.iterator_t; - let double_ended_iterator_t = &cx.toks.double_ended_iterator_t; + + let option = cx.toks.option(); + let clone_t = cx.toks.clone_t(); + let iterator_t = cx.toks.iterator_t(); + let double_ended_iterator_t = cx.toks.double_ended_iterator_t(); let mut step_forward = IteratorNext::default(); let mut step_backward = IteratorNextBack::default(); @@ -1017,7 +1037,7 @@ fn build_into_iter_impl( )?; for FieldSpec { name, kind, .. } in field_specs { - field_clone.push(quote!(#name: #clone::clone(&self.#name))); + field_clone.push(quote!(#name: #clone_t::clone(&self.#name))); match kind { FieldKind::Simple => { @@ -1031,7 +1051,7 @@ fn build_into_iter_impl( } => { field_decls.push(quote!(#name: #as_storage::IntoIter)); init.push(quote!(#name: #storage::into_iter(self.#name))); - clone_bounds.push(quote!(#as_storage::IntoIter: #clone)); + clone_bounds.push(quote!(#as_storage::IntoIter: #clone_t)); } } } @@ -1046,7 +1066,7 @@ fn build_into_iter_impl( } #[automatically_derived] - impl #clone for #type_name where V: Clone, #(#clone_bounds,)* { + impl #clone_t for #type_name where V: Clone, #(#clone_bounds,)* { #[inline] fn clone(&self) -> Self { Self { @@ -1143,14 +1163,15 @@ fn build_entry_impl(cx: &Ctxt<'_>, field_specs: &[FieldSpec<'_>]) -> Result Self { - Self { - array_into_iter: quote!(::core::array::IntoIter), - bool_type: quote!(::core::primitive::bool), - clone: quote!(::core::clone::Clone), - copy: quote!(::core::marker::Copy), - default: quote!(::core::default::Default), - double_ended_iterator_t: quote!(::core::iter::DoubleEndedIterator), - eq: quote!(::core::cmp::Eq), - into_iter: quote!(::core::iter::IntoIterator::into_iter), - iterator_t: quote!(::core::iter::Iterator), - iterator_flatten: quote!(::core::iter::Flatten), - key_trait: quote!(#krate::key::Key), - mem: quote!(::core::mem), - option: quote!(::core::option::Option), - partial_eq: quote!(::core::cmp::PartialEq), - slice_iter_mut: quote!(::core::slice::IterMut), - slice_iter: quote!(::core::slice::Iter), - storage_trait: quote!(#krate::storage::Storage), - iterator_flat_map: quote!(::core::iter::FlatMap), - storage_entry_trait: quote!(#krate::storage::entry::StorageEntry), - occupied_entry_trait: quote!(#krate::storage::entry::OccupiedEntry), - vacant_entry_trait: quote!(#krate::storage::entry::VacantEntry), - entry_enum: quote!(#krate::storage::entry::Entry), - option_bucket_option: quote!(#krate::option_bucket::OptionBucket), - option_bucket_some: quote!(#krate::option_bucket::SomeBucket), - option_bucket_none: quote!(#krate::option_bucket::NoneBucket), +// Builder function to use when constructing token. +type Builder = fn(&Toks<'_>) -> Path; + +// Helper macro to define re-usable token paths. +macro_rules! toks { + ($vis:vis struct $ident:ident <$lt:lifetime> { $($field:ident = [$($path:tt)*]),* $(,)? }) => { + $vis struct $ident<$lt> { + core: Path, + crate_prefix: &$lt Path, + $($field: Builder,)* } + + impl<$lt> $ident<$lt> { + /// Construct path tokens with the given prefix. + pub(crate) fn new(crate_prefix: &$lt Path) -> Self { + let core = leading_path(["core"]); + + Self { + core, + crate_prefix, + $($field: toks!(@path $($path)*),)* + } + } + + $( + #[inline] + #[allow(clippy::wrong_self_convention)] + $vis fn $field(&self) -> Path { + let f = self.$field; + f(self) + } + )* + } + }; + + (@path ::core $(:: $rest:tt)*) => { + |s| suffixed(&s.core, [$(stringify!($rest)),*]) + }; + + (@path crate $(:: $rest:tt)*) => { + |s| suffixed(&s.crate_prefix, [$(stringify!($rest)),*]) + }; +} + +toks! { + pub(crate) struct Toks<'a> { + array_into_iter = [::core::array::IntoIter], + bool_type = [::core::primitive::bool], + clone_t = [::core::clone::Clone], + copy_t = [::core::marker::Copy], + default_t = [::core::default::Default], + double_ended_iterator_t = [::core::iter::DoubleEndedIterator], + entry_enum = [crate::storage::entry::Entry], + eq_t = [::core::cmp::Eq], + hash_t = [::core::hash::Hash], + hasher_t = [::core::hash::Hasher], + into_iterator_t = [::core::iter::IntoIterator], + iterator_flat_map = [::core::iter::FlatMap], + iterator_flatten = [::core::iter::Flatten], + iterator_t = [::core::iter::Iterator], + key_t = [crate::key::Key], + mem = [::core::mem], + occupied_entry_t = [crate::storage::entry::OccupiedEntry], + option = [::core::option::Option], + option_bucket_none = [crate::option_bucket::NoneBucket], + option_bucket_option = [crate::option_bucket::OptionBucket], + option_bucket_some = [crate::option_bucket::SomeBucket], + ord_t = [::core::cmp::Ord], + ordering = [::core::cmp::Ordering], + partial_eq_t = [::core::cmp::PartialEq], + partial_ord_t = [::core::cmp::PartialOrd], + slice_iter = [::core::slice::Iter], + slice_iter_mut = [::core::slice::IterMut], + storage_entry_t = [crate::storage::entry::StorageEntry], + storage_t = [crate::storage::Storage], + vacant_entry_t = [crate::storage::entry::VacantEntry], + } +} + +/// Construct a leading path. +pub(crate) fn leading_path(parts: [&'static str; N]) -> Path { + let mut path = Path { + leading_colon: Some(::default()), + segments: syn::punctuated::Punctuated::default(), + }; + + for part in parts { + let segment = syn::PathSegment::from(syn::Ident::new(part, Span::call_site())); + path.segments.push(segment); } + + path +} + +/// Add the given parts as suffix to the specified prefix path. +fn suffixed(prefix: &Path, parts: [&'static str; N]) -> Path { + let mut path = prefix.clone(); + + for part in parts { + let segment = syn::PathSegment::from(syn::Ident::new(part, Span::call_site())); + path.segments.push(segment); + } + + path } pub(crate) struct Ctxt<'a> { /// Errors collected in the context. errors: RefCell>, /// Generated tokens. - pub(crate) toks: &'a Toks, + pub(crate) toks: &'a Toks<'a>, /// Input ast. pub(crate) ast: &'a DeriveInput, /// Usable lifetime parameter. @@ -77,7 +122,7 @@ pub(crate) struct Ctxt<'a> { } impl<'a> Ctxt<'a> { - pub(crate) fn new(tokens: &'a Toks, ast: &'a DeriveInput, lt: &'a syn::Lifetime) -> Self { + pub(crate) fn new(tokens: &'a Toks<'a>, ast: &'a DeriveInput, lt: &'a syn::Lifetime) -> Self { Self { errors: RefCell::new(Vec::new()), toks: tokens, diff --git a/fixed-map-derive/src/lib.rs b/fixed-map-derive/src/lib.rs index cef94e1..e9c7b72 100644 --- a/fixed-map-derive/src/lib.rs +++ b/fixed-map-derive/src/lib.rs @@ -144,7 +144,8 @@ pub fn storage_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream let ast = syn::parse_macro_input!(input as DeriveInput); let lt = syn::Lifetime::new("'a", ast.span()); - let tokens = context::Toks::new("e!(fixed_map)); + let crate_prefix = context::leading_path(["fixed_map"]); + let tokens = context::Toks::new(&crate_prefix); let cx = context::Ctxt::new(&tokens, &ast, <); let result = impl_storage(&cx); diff --git a/fixed-map-derive/src/unit_variants.rs b/fixed-map-derive/src/unit_variants.rs index 8e44558..3b94fe5 100644 --- a/fixed-map-derive/src/unit_variants.rs +++ b/fixed-map-derive/src/unit_variants.rs @@ -1,5 +1,5 @@ use proc_macro2::{Span, TokenStream}; -use quote::quote; +use quote::{format_ident, quote}; use syn::{DataEnum, Ident}; use crate::context::Ctxt; @@ -8,82 +8,53 @@ use crate::context::Ctxt; pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result { let vis = &cx.ast.vis; let ident = &cx.ast.ident; - let lt = cx.lt; - let clone = &cx.toks.clone; - let copy = &cx.toks.copy; - let default = &cx.toks.default; - let eq = &cx.toks.eq; - let into_iter = &cx.toks.into_iter; - let iterator = &cx.toks.iterator_t; - let iterator_flatten = &cx.toks.iterator_flatten; - let key_trait = &cx.toks.key_trait; - let mem = &cx.toks.mem; - let option = &cx.toks.option; - let partial_eq = &cx.toks.partial_eq; - let slice_iter = &cx.toks.slice_iter; - let slice_iter_mut = &cx.toks.slice_iter_mut; - let array_into_iter = &cx.toks.array_into_iter; - let storage_trait = &cx.toks.storage_trait; - let iterator_flat_map = &cx.toks.iterator_flat_map; - let storage_entry_trait = &cx.toks.storage_entry_trait; - let occupied_entry_trait = &cx.toks.occupied_entry_trait; - let vacant_entry_trait = &cx.toks.vacant_entry_trait; - let entry_enum = &cx.toks.entry_enum; - let option_bucket_option = &cx.toks.option_bucket_option; - let option_bucket_some = &cx.toks.option_bucket_some; - let option_bucket_none = &cx.toks.option_bucket_none; + + let array_into_iter = cx.toks.array_into_iter(); + let clone_t = cx.toks.clone_t(); + let copy_t = cx.toks.copy_t(); + let default = cx.toks.default_t(); + let entry_enum = cx.toks.entry_enum(); + let eq = cx.toks.eq_t(); + let hash = cx.toks.hash_t(); + let hasher = cx.toks.hasher_t(); + let into_iterator_t = cx.toks.into_iterator_t(); + let iterator_flat_map = cx.toks.iterator_flat_map(); + let iterator_flatten = cx.toks.iterator_flatten(); + let iterator_t = cx.toks.iterator_t(); + let key_trait = cx.toks.key_t(); + let mem = cx.toks.mem(); + let occupied_entry_t = cx.toks.occupied_entry_t(); + let option = cx.toks.option(); + let option_bucket_none = cx.toks.option_bucket_none(); + let option_bucket_option = cx.toks.option_bucket_option(); + let option_bucket_some = cx.toks.option_bucket_some(); + let ord_t = cx.toks.ord_t(); + let ordering = cx.toks.ordering(); + let partial_eq_t = cx.toks.partial_eq_t(); + let partial_ord_t = cx.toks.partial_ord_t(); + let slice_iter = cx.toks.slice_iter(); + let slice_iter_mut = cx.toks.slice_iter_mut(); + let storage_entry_t = cx.toks.storage_entry_t(); + let storage_trait = cx.toks.storage_t(); + let vacant_entry_t = cx.toks.vacant_entry_t(); let const_wrapper = Ident::new( &format!("__IMPL_KEY_FOR_{}", cx.ast.ident), Span::call_site(), ); - let mut len = Vec::new(); - let mut is_empty = Vec::new(); - let mut pattern = Vec::new(); - let mut names = Vec::new(); - let mut fields = Vec::new(); - let mut field_inits = Vec::new(); - let mut contains_key = Vec::new(); - let mut get = Vec::new(); - let mut get_mut = Vec::new(); - let mut insert = Vec::new(); - let mut remove = Vec::new(); - let mut retain = Vec::new(); - let mut keys_iter_init = Vec::new(); - let mut iter_init = Vec::new(); - let mut entry = Vec::new(); + let count = en.variants.len(); + let mut variants = Vec::with_capacity(count); + let mut names = Vec::with_capacity(count); + let mut field_inits = Vec::with_capacity(count); for (index, variant) in en.variants.iter().enumerate() { - let var = &variant.ident; - let name = Ident::new(&format!("f{}", index), Span::call_site()); - - len.push(quote!(usize::from(#option::is_some(#name)))); - is_empty.push(quote!(#option::is_none(#name))); field_inits.push(quote!(#option::None)); - fields.push(quote!(#option)); - pattern.push(quote!(#ident::#var)); - contains_key.push(quote!(#option::is_some(#name))); - get.push(quote!(#option::as_ref(#name))); - get_mut.push(quote!(#option::as_mut(#name))); - insert.push(quote!(#mem::replace(#name, #option::Some(value)))); - remove.push(quote!(#mem::take(#name))); - retain.push(quote! { - if let Some(val) = #option::as_mut(#name) { - if !func(#ident::#var, val) { - *#name = None; - } - } - }); - keys_iter_init.push(quote!(if #name.is_some() { Some(#ident::#var) } else { None })); - iter_init.push(quote!((#ident::#var, #name))); - names.push(name.clone()); - entry.push(quote!(option_to_entry(#name, key))); + variants.push(&variant.ident); + names.push(format_ident!("_{}", index)); } - let count = en.variants.len(); - let entry_impl = if cfg!(feature = "entry") { quote! { #vis struct VacantEntry<#lt, V> { @@ -92,7 +63,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl<#lt, V> #vacant_entry_trait<#lt, #ident, V> for VacantEntry<#lt, V> { + impl<#lt, V> #vacant_entry_t<#lt, #ident, V> for VacantEntry<#lt, V> { #[inline] fn key(&self) -> #ident { self.key @@ -110,7 +81,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl<#lt, V> #occupied_entry_trait<#lt, #ident, V> for OccupiedEntry<#lt, V> { + impl<#lt, V> #occupied_entry_t<#lt, #ident, V> for OccupiedEntry<#lt, V> { #[inline] fn key(&self) -> #ident { self.key @@ -151,7 +122,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #storage_entry_trait<#ident, V> for Storage { + impl #storage_entry_t<#ident, V> for Storage { type Occupied<#lt> = OccupiedEntry<#lt, V> where V: #lt; type Vacant<#lt> = VacantEntry<#lt, V> where V: #lt; @@ -160,7 +131,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match key { - #(#pattern => #entry,)* + #(#ident::#variants => option_to_entry(#names, key),)* } } } @@ -177,30 +148,100 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result } #[automatically_derived] - impl #clone for Storage where V: #clone { + impl #clone_t for Storage where V: #clone_t { #[inline] fn clone(&self) -> Storage { Storage { - data: #clone::clone(&self.data), + data: #clone_t::clone(&self.data), } } } #[automatically_derived] - impl #copy for Storage where V: #copy { + impl #copy_t for Storage where V: #copy_t { } #[automatically_derived] - impl #partial_eq for Storage where V: #partial_eq{ + impl #partial_eq_t for Storage where V: #partial_eq_t { #[inline] fn eq(&self, other: &Storage) -> bool { - self.data == other.data + #partial_eq_t::eq(&self.data, &other.data) + } + + #[inline] + fn ne(&self, other: &Storage) -> bool { + #partial_eq_t::ne(&self.data, &other.data) } } #[automatically_derived] impl #eq for Storage where V: #eq {} + #[automatically_derived] + impl #hash for Storage where V: #hash { + #[inline] + fn hash(&self, state: &mut H) + where + H: #hasher, + { + #hash::hash(&self.data, state); + } + } + + #[automatically_derived] + impl #partial_ord_t for Storage where V: #partial_ord_t { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<#ordering> { + #partial_ord_t::partial_cmp(&self.data, &other.data) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + #partial_ord_t::lt(&self.data, &other.data) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + #partial_ord_t::le(&self.data, &other.data) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + #partial_ord_t::gt(&self.data, &other.data) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + #partial_ord_t::ge(&self.data, &other.data) + } + } + + #[automatically_derived] + impl #ord_t for Storage where V: #ord_t { + #[inline] + fn cmp(&self, other: &Self) -> #ordering { + #ord_t::cmp(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { data: #ord_t::max(self.data, other.data) } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { data: #ord_t::min(self.data, other.data) } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: #partial_ord_t + { + Self { data: #ord_t::clamp(self.data, min.data, max.data) } + } + } + #[automatically_derived] impl #default for Storage { #[inline] @@ -235,13 +276,13 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn len(&self) -> usize { let [#(#names),*] = &self.data; - 0 #(+ #len)* + 0 #(+ usize::from(#option::is_some(#names)))* } #[inline] fn is_empty(&self) -> bool { let [#(#names),*] = &self.data; - true #(&& #is_empty)* + true #(&& #option::is_none(#names))* } #[inline] @@ -249,7 +290,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match key { - #(#pattern => #insert,)* + #(#ident::#variants => #mem::replace(#names, #option::Some(value)),)* } } @@ -258,7 +299,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &self.data; match value { - #(#pattern => #contains_key,)* + #(#ident::#variants => #option::is_some(#names),)* } } @@ -267,7 +308,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &self.data; match value { - #(#pattern => #get,)* + #(#ident::#variants => #option::as_ref(#names),)* } } @@ -276,7 +317,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match value { - #(#pattern => #get_mut,)* + #(#ident::#variants => #option::as_mut(#names),)* } } @@ -285,7 +326,7 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result let [#(#names),*] = &mut self.data; match value { - #(#pattern => #remove,)* + #(#ident::#variants => #mem::take(#names),)* } } @@ -295,7 +336,12 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result F: FnMut(#ident, &mut V) -> bool { let [#(#names),*] = &mut self.data; - #(#retain)* + + #(if let #option::Some(val) = #option::as_mut(#names) { + if !func(#ident::#variants, val) { + *#names = None; + } + })* } #[inline] @@ -306,35 +352,35 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result #[inline] fn iter(&self) -> Self::Iter<'_> { let [#(#names),*] = &self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_ref(v)?))) } #[inline] fn keys(&self) -> Self::Keys<'_> { let [#(#names),*] = &self.data; - #iterator::flatten(#into_iter([#(#keys_iter_init),*])) + #iterator_t::flatten(#into_iterator_t::into_iter([#(if #names.is_some() { Some(#ident::#variants) } else { None }),*])) } #[inline] fn values(&self) -> Self::Values<'_> { - #iterator::flatten(#into_iter(&self.data)) + #iterator_t::flatten(#into_iterator_t::into_iter(&self.data)) } #[inline] fn iter_mut(&mut self) -> Self::IterMut<'_> { let [#(#names),*] = &mut self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, #option::as_mut(v)?))) } #[inline] fn values_mut(&mut self) -> Self::ValuesMut<'_> { - #iterator::flatten(#into_iter(&mut self.data)) + #iterator_t::flatten(#into_iterator_t::into_iter(&mut self.data)) } #[inline] fn into_iter(self) -> Self::IntoIter { let [#(#names),*] = self.data; - #iterator::flat_map(#into_iter([#(#iter_init),*]), |(k, v)| #option::Some((k, v?))) + #iterator_t::flat_map(#into_iterator_t::into_iter([#((#ident::#variants, #names)),*]), |(k, v)| #option::Some((k, v?))) } } diff --git a/src/map.rs b/src/map.rs index 64f69c1..6582de5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,8 @@ //! Contains the fixed [`Map`] implementation. +use core::cmp::{Ord, Ordering, PartialOrd}; use core::fmt; +use core::hash::{Hash, Hasher}; use crate::{key::Key, storage::Storage}; @@ -1028,6 +1030,216 @@ where { } +/// [`Hash`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut set = HashSet::new(); +/// set.insert(a); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// // TODO: support this +/// // let mut set = HashSet::new(); +/// // set.insert(a); +/// ``` +impl Hash for Map +where + K: Key, + K::Storage: Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.storage.hash(state); + } +} + +/// [`PartialOrd`] implementation for a [`Map`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// // TODO: support this +/// // assert!(a > b); +/// ``` +impl PartialOrd for Map +where + K: Key, + K::Storage: PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.storage.partial_cmp(&other.storage) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + self.storage.lt(&other.storage) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + self.storage.le(&other.storage) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + self.storage.gt(&other.storage) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + self.storage.ge(&other.storage) + } +} + +/// [`Ord`] implementation for a [`Map`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First, 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// let mut list = vec![a, b]; +/// list.sort(); +/// +/// assert_eq!(list, [b, a]); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Map}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Map::new(); +/// a.insert(Key::First(true), 1); +/// +/// let mut b = Map::new(); +/// b.insert(Key::Second, 1); +/// +/// // TODO: support this +/// // let mut list = vec![a, b]; +/// // list.sort(); +/// ``` +impl Ord for Map +where + K: Key, + K::Storage: Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.storage.cmp(&other.storage) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { + storage: self.storage.max(other.storage), + } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { + storage: self.storage.min(other.storage), + } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self { + Self { + storage: self.storage.clamp(min.storage, max.storage), + } + } +} + impl<'a, K, V> IntoIterator for &'a Map where K: Key, diff --git a/src/set.rs b/src/set.rs index dea79bf..3203ba5 100644 --- a/src/set.rs +++ b/src/set.rs @@ -1,6 +1,8 @@ //! Contains the fixed [`Set`] implementation. +use core::cmp::Ordering; use core::fmt; +use core::hash::{Hash, Hasher}; use core::iter; use crate::key::Key; @@ -585,6 +587,216 @@ where { } +/// [`Hash`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut set = HashSet::new(); +/// set.insert(a); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use std::collections::HashSet; +/// +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// // TODO: support this +/// // let mut set = HashSet::new(); +/// // set.insert(a); +/// ``` +impl Hash for Set +where + K: Key, + K::Storage<()>: Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.storage.hash(state); + } +} + +/// [`PartialOrd`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// assert!(a > b); +/// assert!(a >= b); +/// assert!(!(a < b)); +/// assert!(!(a <= b)); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// // TODO: support this +/// // assert!(a > b); +/// ``` +impl PartialOrd for Set +where + K: Key, + K::Storage<()>: PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.storage.partial_cmp(&other.storage) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + self.storage.lt(&other.storage) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + self.storage.le(&other.storage) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + self.storage.gt(&other.storage) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + self.storage.ge(&other.storage) + } +} + +/// [`Ord`] implementation for a [`Set`]. +/// +/// # Examples +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First, +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// let mut list = vec![a, b]; +/// list.sort(); +/// +/// assert_eq!(list, [b, a]); +/// ``` +/// +/// Using a composite key: +/// +/// ``` +/// use fixed_map::{Key, Set}; +/// +/// #[derive(Debug, Clone, Copy, Hash, Key)] +/// enum Key { +/// First(bool), +/// Second, +/// } +/// +/// let mut a = Set::new(); +/// a.insert(Key::First(true)); +/// +/// let mut b = Set::new(); +/// b.insert(Key::Second); +/// +/// // TODO: support this +/// // let mut list = vec![a, b]; +/// // list.sort(); +/// ``` +impl Ord for Set +where + K: Key, + K::Storage<()>: Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.storage.cmp(&other.storage) + } + + #[inline] + fn max(self, other: Self) -> Self { + Self { + storage: self.storage.max(other.storage), + } + } + + #[inline] + fn min(self, other: Self) -> Self { + Self { + storage: self.storage.min(other.storage), + } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self { + Self { + storage: self.storage.clamp(min.storage, max.storage), + } + } +} + impl<'a, K> IntoIterator for &'a Set where K: Key,