value_traits_derive/
lib.rs

1/*
2 * SPDX-FileCopyrightText: 2025 Tommaso Fontana
3 * SPDX-FileCopyrightText: 2025 Inria
4 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
5 *
6 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7 */
8
9#![warn(missing_docs)]
10#![warn(clippy::missing_errors_doc)]
11#![warn(clippy::missing_panics_doc)]
12
13//! Derive macros for the [`value-traits`](https://docs.rs/value-traits/latest/value_traits/) crate.
14
15use proc_macro::TokenStream;
16use quote::{quote, ToTokens};
17use syn::{parse2, parse_macro_input, AngleBracketedGenericArguments, DeriveInput};
18
19/// Helper function returning the list of parameter names without angle brackets.
20fn get_names(ty_generics_token_stream: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
21    if ty_generics_token_stream.is_empty() {
22        proc_macro2::TokenStream::new()
23    } else {
24        let parsed_args: AngleBracketedGenericArguments =
25            parse2(ty_generics_token_stream)
26                .expect("Failed to parse ty_generics into AngleBracketedGenericArguments. This indicates an unexpected structure in the generic parameters.");
27
28        parsed_args.args.into_token_stream()
29    }
30}
31
32/// A derive macro fully implementing subslices on top of a
33/// [`SliceByValueGet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueGet.html).
34///
35/// The macro defines a structure `<YOUR TYPE>SubsliceImpl` that keeps track of
36/// a reference to a slice, and of the start and end of the subslice.
37/// `<YOUR TYPE>SubsliceImpl` then implements
38/// [`SliceByValueGet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueGet.html)
39/// and
40/// [`SliceByValueSubslice`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSubslice.html).
41///
42/// Note that since this macro has no knowledge of the bounds of the generic
43/// parameters in the implementations of
44/// [`SliceByValue`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValue.html)
45/// and
46/// [`SliceByValueGet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueGet.html),
47/// such bounds must appear in the definition of the type.
48#[proc_macro_derive(Subslices)]
49pub fn subslices(input: TokenStream) -> TokenStream {
50    let mut input = parse_macro_input!(input as DeriveInput);
51
52    let input_ident = input.ident;
53    input.generics.make_where_clause();
54    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
55    let params = &input.generics.params;
56    let ty_generics_token_stream = ty_generics.clone().into_token_stream();
57
58    let names = get_names(ty_generics_token_stream);
59    let subslice_impl = quote::format_ident!("{}SubsliceImpl", input_ident);
60    let mut res = quote! {
61        #[automatically_derived]
62        pub struct #subslice_impl<'__subslice_impl, #params> {
63            slice: &'__subslice_impl #input_ident #ty_generics,
64            range: ::core::ops::Range<usize>,
65        }
66
67        #[automatically_derived]
68        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValue for #subslice_impl<'__subslice_impl, #names> #where_clause {
69            type Value = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
70
71            #[inline]
72            fn len(&self) -> usize {
73                self.range.len()
74            }
75        }
76
77        #[automatically_derived]
78        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueGet for #subslice_impl<'__subslice_impl, #names> #where_clause  {
79            unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
80                self.slice.get_value_unchecked(index + self.range.start)
81            }
82        }
83
84        #[automatically_derived]
85        impl<'__subslice_impl, '__subslice_gat, #params> ::value_traits::slices::SliceByValueSubsliceGat<'__subslice_gat> for #subslice_impl<'__subslice_impl, #names> #where_clause {
86            type Subslice = #subslice_impl<'__subslice_gat, #names>;
87        }
88
89        #[automatically_derived]
90        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSubsliceGat<'__subslice_impl> for #input_ident #ty_generics #where_clause  {
91            type Subslice = #subslice_impl<'__subslice_impl, #names>;
92        }
93    };
94
95    for range_type in [
96        quote! { core::ops::Range<usize> },
97        quote! { core::ops::RangeFrom<usize> },
98        quote! { core::ops::RangeToInclusive<usize> },
99        quote! { core::ops::RangeFull },
100        quote! { core::ops::RangeInclusive<usize> },
101        quote! { core::ops::RangeTo<usize> },
102    ] {
103        res.extend(quote! {
104            #[automatically_derived]
105            impl #impl_generics ::value_traits::slices::SliceByValueSubsliceRange<#range_type> for #input_ident #ty_generics #where_clause {
106                unsafe fn get_subslice_unchecked(
107                    &self,
108                    range: #range_type,
109                ) -> ::value_traits::slices::Subslice<'_, Self> {
110                    #subslice_impl {
111                        slice: &self,
112                        range: ::value_traits::slices::ComposeRange::compose(&range, 0..self.len()),
113                    }
114                }
115            }
116            #[automatically_derived]
117            impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSubsliceRange<#range_type>
118                for #subslice_impl<'__subslice_impl, #names> #where_clause
119            {
120                unsafe fn get_subslice_unchecked(
121                    &self,
122                    range: #range_type,
123                ) -> ::value_traits::slices::Subslice<'_, Self> {
124                    #subslice_impl {
125                        slice: self.slice,
126                        range: ::value_traits::slices::ComposeRange::compose(&range, self.range.clone()),
127                    }
128                }
129            }
130        });
131    }
132
133    res.into()
134}
135
136/// A derive macro fully implementing mutable subslices on top of a
137/// [`SliceByValueSet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSet.html)/[`SliceByValueRepl`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueRepl.html)
138/// for which the derive macro [`Subslices`] has been already applied.
139///
140/// The macro defines a structure `<YOUR TYPE>SubsliceImplMut` that keeps track
141/// of a mutable reference to a slice, and of the start and end of the subslice.
142/// `<YOUR TYPE>SubsliceImplMut` then implements
143/// [`SliceByValueGet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueGet.html),
144/// [`SliceByValueSet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSet.html),
145/// [`SliceByValueRepl`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueRepl.html),
146/// [`SliceByValueSubslice`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSubslice.html),
147/// and
148/// [`SliceByValueSubsliceMut`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSubsliceMut.html).
149///
150/// Note that
151/// [`SliceByValueSubslice`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSubslice.html)
152/// methods will return the `<YOUR TYPE>SubsliceImpl` structure generated by the
153/// [`Subslices`] macro.
154///
155/// Moreover, since this macro has no knowledge of the bounds of the generic
156/// parameters in the implementations of
157/// [`SliceByValueSet`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueSet.html)
158/// and
159/// [`SliceByValueRepl`](https://docs.rs/value-traits/latest/value_traits/slices/trait.SliceByValueRepl.html),
160/// such bounds must appear in the definition of the type.
161#[proc_macro_derive(SubslicesMut)]
162pub fn subslices_mut(input: TokenStream) -> TokenStream {
163    let mut input = parse_macro_input!(input as DeriveInput);
164
165    let input_ident = input.ident;
166    input.generics.make_where_clause();
167    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
168    let params = &input.generics.params;
169    let ty_generics_token_stream = ty_generics.clone().into_token_stream();
170
171    let names = get_names(ty_generics_token_stream);
172    let subslice_impl = quote::format_ident!("{}SubsliceImpl", input_ident);
173    let subslice_impl_mut = quote::format_ident!("{}SubsliceImplMut", input_ident);
174    let mut res = quote! {
175        #[automatically_derived]
176        pub struct #subslice_impl_mut<'__subslice_impl, #params> {
177            slice: &'__subslice_impl mut #input_ident #ty_generics,
178            range: ::core::ops::Range<usize>,
179        }
180
181        #[automatically_derived]
182        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValue for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
183            type Value = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
184
185            #[inline]
186            fn len(&self) -> usize {
187                self.range.len()
188            }
189        }
190
191        #[automatically_derived]
192        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueGet for #subslice_impl_mut<'__subslice_impl, #names> #where_clause  {
193            unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
194                self.slice.get_value_unchecked(index + self.range.start)
195            }
196        }
197
198        #[automatically_derived]
199        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSet for #subslice_impl_mut<'__subslice_impl, #names> #where_clause  {
200            unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
201                self.slice.set_value_unchecked(index + self.range.start, value)
202            }
203        }
204
205        #[automatically_derived]
206        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueRepl for #subslice_impl_mut<'__subslice_impl, #names> #where_clause  {
207            unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
208                self.slice.replace_value_unchecked(index + self.range.start, value)
209            }
210        }
211
212        #[automatically_derived]
213        impl<'__subslice_impl, '__subslice_gat, #params> ::value_traits::slices::SliceByValueSubsliceGat<'__subslice_gat> for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
214            type Subslice = #subslice_impl<'__subslice_gat, #names>;
215        }
216
217        #[automatically_derived]
218        impl<'__subslice_impl, '__subslice_gat, #params> ::value_traits::slices::SliceByValueSubsliceGatMut<'__subslice_gat> for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
219            type SubsliceMut = #subslice_impl_mut<'__subslice_gat, #names>;
220        }
221
222        #[automatically_derived]
223        impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSubsliceGatMut<'__subslice_impl> for #input_ident #ty_generics #where_clause  {
224            type SubsliceMut = #subslice_impl_mut<'__subslice_impl, #names>;
225        }
226
227    };
228
229    for range_type in [
230        quote! { ::core::ops::Range<usize> },
231        quote! { ::core::ops::RangeFrom<usize> },
232        quote! { ::core::ops::RangeToInclusive<usize> },
233        quote! { ::core::ops::RangeFull },
234        quote! { ::core::ops::RangeInclusive<usize> },
235        quote! { ::core::ops::RangeTo<usize> },
236    ] {
237        // Impl subslice mut traits for the original type
238        res.extend(quote!{
239            #[automatically_derived]
240            impl #impl_generics ::value_traits::slices::SliceByValueSubsliceRangeMut<#range_type> for #input_ident #ty_generics #where_clause {
241                unsafe fn get_subslice_unchecked_mut(
242                    &mut self,
243                    range: #range_type,
244                ) -> ::value_traits::slices::SubsliceMut<'_, Self> {
245                    let len = self.len();
246                    #subslice_impl_mut {
247                        slice: self,
248                        range: ::value_traits::slices::ComposeRange::compose(&range, 0..len),
249                    }
250                }
251            }
252            #[automatically_derived]
253            impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSubsliceRange<#range_type>
254                for #subslice_impl_mut<'__subslice_impl, #names> #where_clause
255            {
256                unsafe fn get_subslice_unchecked(
257                    &self,
258                    range: #range_type,
259                ) -> ::value_traits::slices::Subslice<'_, Self> {
260                    #subslice_impl {
261                        slice: &*self.slice,
262                        range: ::value_traits::slices::ComposeRange::compose(&range, self.range.clone()),
263                    }
264                }
265            }
266            #[automatically_derived]
267            impl<'__subslice_impl, #params> ::value_traits::slices::SliceByValueSubsliceRangeMut<#range_type>
268                for #subslice_impl_mut<'__subslice_impl, #names> #where_clause
269            {
270                unsafe fn get_subslice_unchecked_mut(
271                    &mut self,
272                    range: #range_type,
273                ) -> ::value_traits::slices::SubsliceMut<'_, Self> {
274                    #subslice_impl_mut {
275                        slice: self.slice,
276                        range: ::value_traits::slices::ComposeRange::compose(&range, self.range.clone()),
277                    }
278                }
279            }
280        });
281    }
282
283    res.into()
284}
285
286/// A derive macro fully implementing
287/// [`IterateByValue`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValue.html)
288/// and
289/// [`IterateByValueFrom`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValueFrom.html)
290/// for subslices on top of a the `<YOUR TYPE>SubsliceImpl` structure generated
291/// by the derive macro [`Subslices`].
292///
293/// The macro defines a structure `<YOUR TYPE>Iter` that keeps track of a
294/// mutable reference to a slice and of a current iteration range; the structure
295/// is used to implement
296/// [`IterateByValue`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValue.html)
297/// and
298/// [`IterateByValueFrom`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValueFrom.html)
299/// on `<YOUR TYPE>SubsliceImpl`.
300#[proc_macro_derive(Iterators)]
301pub fn iterators(input: TokenStream) -> TokenStream {
302    let mut input = parse_macro_input!(input as DeriveInput);
303
304    let input_ident = input.ident;
305    input.generics.make_where_clause();
306    let (_impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
307    let params = &input.generics.params;
308    let ty_generics_token_stream = ty_generics.clone().into_token_stream();
309
310    let names = get_names(ty_generics_token_stream);
311    let subslice_impl = quote::format_ident!("{}SubsliceImpl", input_ident);
312    let iter = quote::format_ident!("{}Iter", input_ident);
313    quote! {
314        #[automatically_derived]
315        pub struct #iter<'__iter_ref, #params> {
316            subslice: &'__iter_ref #input_ident #ty_generics,
317            range: ::core::ops::Range<usize>,
318        }
319
320        #[automatically_derived]
321        impl<'__iter_ref, #params> #iter<'__iter_ref, #names> #where_clause {
322            pub fn new(subslice: &'__iter_ref #input_ident #ty_generics) -> Self {
323                let len = subslice.len();
324                Self {
325                    subslice,
326                    range: 0..len,
327                }
328            }
329            pub fn new_with_range(subslice: &'__iter_ref #input_ident #ty_generics, range: ::core::ops::Range<usize>) -> Self {
330                Self {
331                    subslice,
332                    range,
333                }
334            }
335        }
336
337        /*#[automatically_derived]
338        impl<#params> ::value_traits::iter::IterateByValue for #input_ident #ty_generics #where_clause {
339            type Item = <Self as ::value_traits::slices::SliceByValue>::Value;
340            type Iter<'__iter_ref>
341                = #iter<'__iter_ref, #names>
342            where
343                Self: '__iter_ref;
344
345            #[inline]
346            fn iter_value(&self) -> Self::Iter<'_> {
347                #iter::new(self)
348            }
349        }
350
351        #[automatically_derived]
352        impl<#params> ::value_traits::iter::IterateByValueFrom for #input_ident #ty_generics #where_clause {
353            type IterFrom<'__iter_ref>
354                = #iter<'__iter_ref, #names>
355            where
356                Self: '__iter_ref;
357
358            #[inline]
359            fn iter_value_from(&self, from: usize) -> Self::IterFrom<'_> {
360                let len = self.len();
361                assert!(from <= len, "index out of bounds: the len is {len} but the starting index is {from}");
362                #iter::new_with_range(self, from..len)
363            }
364        }*/
365
366        #[automatically_derived]
367        /// Ideally we would like to also implement [`::core::iter::Iterator::advance_by`], but it is
368        /// nightly, and [`::core::iter::Iterator::skip`], [`::core::iter::Iterator::take`], [`::core::iter::Iterator::step_by`],
369        /// as we can do it more efficiently, but the [`::core::iter::Iterator`] trait definition
370        /// doesn't allow to return an arbitrary type.
371        impl<'__iter_ref, #params> ::core::iter::Iterator for #iter<'__iter_ref, #names> #where_clause {
372            type Item = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
373
374            #[inline]
375            fn next(&mut self) -> Option<Self::Item> {
376                if self.range.is_empty() {
377                    return ::core::option::Option::None;
378                }
379                let value = unsafe { self.subslice.get_value_unchecked(self.range.start) };
380                self.range.start += 1;
381                ::core::option::Option::Some(value)
382            }
383
384            /// Since we are indexing into a subslice, we can implement
385            /// [`::core::iter::Iterator::nth`] without needing to consume the first `n` elements.
386            #[inline]
387            fn nth(&mut self, n: usize) -> Option<Self::Item> {
388                if n >= self.range.end {
389                    self.range.start = self.range.end; // consume the ::core::iter::iterator
390                    return ::core::option::Option::None;
391                }
392                let value = unsafe { self.subslice.get_value_unchecked(self.range.start + n) };
393                self.range.start += n + 1;
394                ::core::option::Option::Some(value)
395            }
396
397            #[inline]
398            fn size_hint(&self) -> (usize, Option<usize>) {
399                let len = self.range.len();
400                (len, Some(len))
401            }
402        }
403
404        impl<'__iter_ref, #params> ::core::iter::DoubleEndedIterator for #iter<'__iter_ref, #names> #where_clause {
405            #[inline]
406            fn next_back(&mut self) -> Option<Self::Item> {
407                if self.range.is_empty() {
408                    return ::core::option::Option::None;
409                }
410                self.range.end -= 1;
411                let value = unsafe { self.subslice.get_value_unchecked(self.range.end) };
412                ::core::option::Option::Some(value)
413            }
414        }
415
416        impl<'__iter_ref, #params> ::core::iter::ExactSizeIterator for #iter<'__iter_ref, #names> #where_clause {
417            #[inline]
418            fn len(&self) -> usize {
419                self.range.len()
420            }
421        }
422
423        #[automatically_derived]
424        impl<'__subslice_impl, '__iter_ref, #params> ::value_traits::iter::IterateByValueGat<'__iter_ref> for #subslice_impl<'__subslice_impl, #names> #where_clause {
425            type Item = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
426            type Iter = #iter<'__iter_ref, #names>;
427        }
428
429        #[automatically_derived]
430        impl<'__subslice_impl, #params> ::value_traits::iter::IterateByValue for #subslice_impl<'__subslice_impl, #names> #where_clause {
431            #[inline]
432            fn iter_value(&self) -> ::value_traits::iter::Iter<'_, Self> {
433                #iter::new(self.slice)
434            }
435        }
436
437        #[automatically_derived]
438        impl<'__subslice_impl, '__iter_ref,#params> ::value_traits::iter::IterateByValueFromGat<'__iter_ref> for #subslice_impl<'__subslice_impl, #names> #where_clause {
439            type Item = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
440            type IterFrom = #iter<'__iter_ref, #names>;
441        }
442
443        #[automatically_derived]
444        impl<'__subslice_impl, #params> ::value_traits::iter::IterateByValueFrom for #subslice_impl<'__subslice_impl, #names> #where_clause {
445            #[inline]
446            fn iter_value_from(&self, from: usize) -> ::value_traits::iter::IterFrom<'_, Self> {
447                let len = self.len();
448                assert!(from <= len, "index out of bounds: the len is {len} but the starting index is {from}");
449                let range = ::value_traits::slices::ComposeRange::compose(&(from..), self.range.clone());
450                #iter::new_with_range(self.slice, range)
451            }
452        }
453    }.into()
454}
455
456/// A derive macro that implements
457/// [`IterateByValue`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValue.html)
458/// and
459/// [`IterateByValueFrom`](https://docs.rs/value-traits/latest/value_traits/iter/trait.IterateByValueFrom.html)
460/// for mutable subslices on top of the `<YOUR TYPE>SubsliceImplMut` structure
461/// generated by the derive macro [`SubslicesMut`].
462///
463/// To call this macro, you first need to derive both [`SubslicesMut`] and
464/// [`Iterators`] on the same struct, as this macro uses the `<YOUR TYPE>Iter`
465/// structure defined by [`Iterators`].
466#[proc_macro_derive(IteratorsMut)]
467pub fn iterators_mut(input: TokenStream) -> TokenStream {
468    let mut input = parse_macro_input!(input as DeriveInput);
469
470    let input_ident = input.ident;
471    input.generics.make_where_clause();
472    let (_impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
473    let params = &input.generics.params;
474    let ty_generics_token_stream = ty_generics.clone().into_token_stream();
475
476    let names = get_names(ty_generics_token_stream);
477    let subslice_impl_mut = quote::format_ident!("{}SubsliceImplMut", input_ident);
478    let iter = quote::format_ident!("{}Iter", input_ident);
479    quote!{
480        #[automatically_derived]
481        impl<'__subslice_impl, '__iter_ref, #params> ::value_traits::iter::IterateByValueGat<'__iter_ref> for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
482            type Item = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
483            type Iter = #iter<'__iter_ref, #names>;
484        }
485
486        #[automatically_derived]
487        impl<'__subslice_impl, #params> ::value_traits::iter::IterateByValue for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
488            fn iter_value(&self) -> ::value_traits::iter::Iter<'_, Self> {
489                #iter::new(self.slice)
490            }
491        }
492
493        #[automatically_derived]
494        impl<'__subslice_impl, '__iter_ref, #params> ::value_traits::iter::IterateByValueFromGat<'__iter_ref> for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
495            type Item = <#input_ident #ty_generics as ::value_traits::slices::SliceByValue>::Value;
496            type IterFrom = #iter<'__iter_ref, #names>;
497        }
498
499        #[automatically_derived]
500        impl<'__subslice_impl, #params> ::value_traits::iter::IterateByValueFrom for #subslice_impl_mut<'__subslice_impl, #names> #where_clause {
501            fn iter_value_from(&self, from: usize) -> ::value_traits::iter::IterFrom<'_, Self> {
502                let len = self.len();
503                assert!(from <= len, "index out of bounds: the len is {len} but the starting index is {from}");
504                let range = ::value_traits::slices::ComposeRange::compose(&(from..), self.range.clone());
505                #iter::new_with_range(self.slice, range)
506            }
507        }
508    }.into()
509}