amplify_derive/
wrapper.rs

1// Rust language amplification derive library providing multiple generic trait
2// implementations, type wrappers, derive macros and other language enhancements
3//
4// Written in 2019-2020 by
5//     Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
6//
7// To the extent possible under law, the author(s) have dedicated all
8// copyright and related and neighboring rights to this software to
9// the public domain worldwide. This software is distributed without
10// any warranty.
11//
12// You should have received a copy of the MIT License
13// along with this software.
14// If not, see <https://opensource.org/licenses/MIT>.
15
16use proc_macro2::TokenStream as TokenStream2;
17use syn::spanned::Spanned;
18use syn::{
19    Data, DeriveInput, Error, Fields, Index, Meta, MetaList, NestedMeta, Path, Result, Type,
20};
21
22use crate::util::get_amplify_crate;
23
24const NAME: &str = "wrapper";
25const EXAMPLE: &str = r#"#[wrapper(LowerHex, Add)]"#;
26
27#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
28enum Wrapper {
29    NoRefs,
30    // Formatting
31    FromStr,
32    Display,
33    Debug,
34    Octal,
35    FromHex,
36    LowerHex,
37    UpperHex,
38    LowerExp,
39    UpperExp,
40    // References
41    Deref,
42    AsRef,
43    AsSlice,
44    Borrow,
45    BorrowSlice,
46    // Indexes
47    Index,
48    IndexRange,
49    IndexFull,
50    IndexFrom,
51    IndexTo,
52    IndexInclusive,
53    IndexToInclusive,
54    // Arithmetics
55    Neg,
56    Add,
57    Sub,
58    Mul,
59    Div,
60    Rem,
61    // Booleans
62    Not,
63    Shl,
64    Shr,
65    BitAnd,
66    BitOr,
67    BitXor,
68    // Group operations
69    Hex,
70    Exp,
71    NumberFmt,
72    RangeOps,
73    MathOps,
74    BoolOps,
75    BitOps,
76}
77
78#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
79enum WrapperMut {
80    NoRefs,
81    // References
82    DerefMut,
83    AsMut,
84    AsSliceMut,
85    BorrowMut,
86    BorrowSliceMut,
87    // Indexes
88    IndexMut,
89    IndexRangeMut,
90    IndexFullMut,
91    IndexFromMut,
92    IndexToMut,
93    IndexInclusiveMut,
94    IndexToInclusiveMut,
95    // Arithmetics
96    AddAssign,
97    SubAssign,
98    MulAssign,
99    DivAssign,
100    RemAssign,
101    ShlAssign,
102    ShrAssign,
103    // Booleans
104    BitAndAssign,
105    BitOrAssign,
106    BitXorAssign,
107    // Group operations
108    RangeMut,
109    MathAssign,
110    BoolAssign,
111    BitAssign,
112}
113
114pub trait FromPath: Sized + Copy + Ord {
115    const IDENT: &'static str;
116    const NO_REFS: Self;
117    fn default_set() -> Vec<Self>;
118    fn is_not_ref(&self) -> bool;
119    fn from_path(path: &Path) -> Result<Option<Self>>;
120    fn populate(self, list: &mut Vec<Self>);
121}
122
123impl FromPath for Wrapper {
124    const IDENT: &'static str = "wrapper";
125    const NO_REFS: Self = Self::NoRefs;
126
127    fn default_set() -> Vec<Self> { vec![Wrapper::AsRef, Wrapper::Borrow] }
128
129    fn is_not_ref(&self) -> bool { *self != Wrapper::AsRef && *self != Wrapper::Borrow }
130
131    fn from_path(path: &Path) -> Result<Option<Self>> {
132        path.segments.first().map_or(
133            Err(attr_err!(path.span(), NAME, "must contain at least one identifier", EXAMPLE)),
134            |segment| {
135                Ok(match segment.ident.to_string().as_str() {
136                    "FromStr" => Some(Wrapper::FromStr),
137                    "Display" => Some(Wrapper::Display),
138                    "Debug" => Some(Wrapper::Debug),
139                    "Octal" => Some(Wrapper::Octal),
140                    "FromHex" => Some(Wrapper::FromHex),
141                    "LowerHex" => Some(Wrapper::LowerHex),
142                    "UpperHex" => Some(Wrapper::UpperHex),
143                    "LowerExp" => Some(Wrapper::LowerExp),
144                    "UpperExp" => Some(Wrapper::UpperExp),
145                    "NoRefs" => Some(Wrapper::NoRefs),
146                    "AsRef" => Some(Wrapper::AsRef),
147                    "AsSlice" => Some(Wrapper::AsSlice),
148                    "Deref" => Some(Wrapper::Deref),
149                    "Borrow" => Some(Wrapper::Borrow),
150                    "BorrowSlice" => Some(Wrapper::BorrowSlice),
151                    "Index" => Some(Wrapper::Index),
152                    "IndexRange" => Some(Wrapper::IndexRange),
153                    "IndexFull" => Some(Wrapper::IndexFull),
154                    "IndexFrom" => Some(Wrapper::IndexFrom),
155                    "IndexTo" => Some(Wrapper::IndexTo),
156                    "IndexInclusive" => Some(Wrapper::IndexInclusive),
157                    "IndexToInclusive" => Some(Wrapper::IndexToInclusive),
158                    "Add" => Some(Wrapper::Add),
159                    "Neg" => Some(Wrapper::Neg),
160                    "Not" => Some(Wrapper::Not),
161                    "Sub" => Some(Wrapper::Sub),
162                    "Mul" => Some(Wrapper::Mul),
163                    "Div" => Some(Wrapper::Div),
164                    "Rem" => Some(Wrapper::Rem),
165                    "Shl" => Some(Wrapper::Shl),
166                    "Shr" => Some(Wrapper::Shr),
167                    "BitAnd" => Some(Wrapper::BitAnd),
168                    "BitOr" => Some(Wrapper::BitOr),
169                    "BitXor" => Some(Wrapper::BitXor),
170
171                    "Hex" => Some(Wrapper::Hex),
172                    "Exp" => Some(Wrapper::Exp),
173                    "NumberFmt" => Some(Wrapper::NumberFmt),
174                    "RangeOps" => Some(Wrapper::RangeOps),
175                    "MathOps" => Some(Wrapper::MathOps),
176                    "BoolOps" => Some(Wrapper::BoolOps),
177                    "BitOps" => Some(Wrapper::BitOps),
178                    _ => None,
179                })
180            },
181        )
182    }
183
184    fn populate(self, list: &mut Vec<Self>) {
185        let ext = match self {
186            Wrapper::Hex => &[Wrapper::LowerHex, Wrapper::UpperHex, Wrapper::FromHex] as &[_],
187            Wrapper::Exp => &[Wrapper::LowerExp, Wrapper::UpperExp] as &[_],
188            Wrapper::NumberFmt => &[
189                Wrapper::LowerHex,
190                Wrapper::UpperHex,
191                Wrapper::LowerExp,
192                Wrapper::UpperExp,
193                Wrapper::Octal,
194            ] as &[_],
195            Wrapper::RangeOps => &[
196                Wrapper::IndexRange,
197                Wrapper::IndexFrom,
198                Wrapper::IndexTo,
199                Wrapper::IndexInclusive,
200                Wrapper::IndexToInclusive,
201                Wrapper::IndexFull,
202            ] as &[_],
203            Wrapper::MathOps => &[
204                Wrapper::Neg,
205                Wrapper::Add,
206                Wrapper::Sub,
207                Wrapper::Mul,
208                Wrapper::Div,
209                Wrapper::Rem,
210            ] as &[_],
211            Wrapper::BoolOps => {
212                &[Wrapper::Not, Wrapper::BitAnd, Wrapper::BitOr, Wrapper::BitXor] as &[_]
213            }
214            Wrapper::BitOps => &[
215                Wrapper::Not,
216                Wrapper::BitAnd,
217                Wrapper::BitOr,
218                Wrapper::BitXor,
219                Wrapper::Shl,
220                Wrapper::Shr,
221            ] as &[_],
222            x => {
223                list.push(x);
224                &[] as &[_]
225            }
226        };
227        list.extend(ext);
228    }
229}
230
231impl Wrapper {
232    pub fn into_token_stream2(
233        self,
234        input: &DeriveInput,
235        from: &Type,
236        field: &TokenStream2,
237    ) -> TokenStream2 {
238        let impl_generics_params = input.generics.params.clone();
239        let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
240        let ident_name = &input.ident;
241        let amplify_crate = get_amplify_crate(input);
242
243        match self {
244            Wrapper::FromStr => quote! {
245                #[automatically_derived]
246                impl #impl_generics ::core::str::FromStr for #ident_name #ty_generics #where_clause
247                {
248                    type Err = <<Self as #amplify_crate::Wrapper>::Inner as ::core::str::FromStr>::Err;
249
250                    #[inline]
251                    fn from_str(s: &str) -> Result<Self, Self::Err> {
252                        use ::core::str::FromStr;
253                        <#from as FromStr>::from_str(s).map(Self::from)
254                    }
255                }
256            },
257            Wrapper::Display => quote! {
258                #[automatically_derived]
259                impl #impl_generics ::core::fmt::Display for #ident_name #ty_generics #where_clause
260                {
261                    #[inline]
262                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
263                        ::core::fmt::Display::fmt(&self.#field, f)
264                    }
265                }
266            },
267            Wrapper::Debug => quote! {
268                #[automatically_derived]
269                impl #impl_generics ::core::fmt::Debug for #ident_name #ty_generics #where_clause
270                {
271                    #[inline]
272                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
273                        ::core::fmt::Debug::fmt(&self.#field, f)
274                    }
275                }
276            },
277            Wrapper::Octal => quote! {
278                #[automatically_derived]
279                impl #impl_generics ::core::fmt::Octal for #ident_name #ty_generics #where_clause
280                {
281                    #[inline]
282                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
283                        ::core::fmt::Octal::fmt(&self.#field, f)
284                    }
285                }
286            },
287            Wrapper::FromHex => quote! {
288                #[automatically_derived]
289                impl #impl_generics #amplify_crate::hex::FromHex for #ident_name #ty_generics #where_clause
290                {
291                    #[inline]
292                    fn from_byte_iter<I>(iter: I) -> Result<Self, #amplify_crate::hex::Error>
293                    where
294                        I: Iterator<Item = Result<u8, #amplify_crate::hex::Error>>
295                            + ExactSizeIterator
296                            + DoubleEndedIterator,
297                    {
298                        <#from as #amplify_crate::hex::FromHex>::from_byte_iter(iter).map(Self::from)
299                    }
300                }
301            },
302            Wrapper::LowerHex => quote! {
303                #[automatically_derived]
304                impl #impl_generics ::core::fmt::LowerHex for #ident_name #ty_generics #where_clause
305                {
306                    #[inline]
307                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
308                        ::core::fmt::LowerHex::fmt(&self.#field, f)
309                    }
310                }
311            },
312            Wrapper::UpperHex => quote! {
313                #[automatically_derived]
314                impl #impl_generics ::core::fmt::UpperHex for #ident_name #ty_generics #where_clause
315                {
316                    #[inline]
317                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
318                        ::core::fmt::UpperHex::fmt(&self.#field, f)
319                    }
320                }
321            },
322            Wrapper::LowerExp => quote! {
323                #[automatically_derived]
324                impl #impl_generics ::core::fmt::LowerExp for #ident_name #ty_generics #where_clause
325                {
326                    #[inline]
327                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
328                        ::core::fmt::LowerExp::fmt(&self.#field, f)
329                    }
330                }
331            },
332            Wrapper::UpperExp => quote! {
333                #[automatically_derived]
334                impl #impl_generics ::core::fmt::UpperExp for #ident_name #ty_generics #where_clause
335                {
336                    #[inline]
337                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
338                        ::core::fmt::UpperExp::fmt(&self.#field, f)
339                    }
340                }
341            },
342            Wrapper::Deref => quote! {
343                #[automatically_derived]
344                impl #impl_generics ::core::ops::Deref for #ident_name #ty_generics #where_clause
345                {
346                    type Target = #from;
347                    #[inline]
348                    fn deref(&self) -> &Self::Target {
349                        &self.#field
350                    }
351                }
352            },
353            Wrapper::AsRef => quote! {
354                #[automatically_derived]
355                impl #impl_generics ::core::convert::AsRef<#from> for #ident_name #ty_generics #where_clause {
356                    #[inline]
357                    fn as_ref(&self) -> &#from {
358                        &self.#field
359                    }
360                }
361            },
362            Wrapper::AsSlice => quote! {
363                #[automatically_derived]
364                impl #impl_generics AsRef<[u8]> for #ident_name #ty_generics #where_clause
365                {
366                    #[inline]
367                    fn as_ref(&self) -> &[u8] {
368                        AsRef::<[u8]>::as_ref(&self.#field)
369                    }
370                }
371            },
372            Wrapper::Borrow => quote! {
373                #[automatically_derived]
374                impl #impl_generics ::core::borrow::Borrow<#from> for #ident_name #ty_generics #where_clause {
375                    #[inline]
376                    fn borrow(&self) -> &#from {
377                        &self.#field
378                    }
379                }
380            },
381            Wrapper::BorrowSlice => quote! {
382                #[automatically_derived]
383                impl #impl_generics ::core::borrow::Borrow<[u8]> for #ident_name #ty_generics #where_clause
384                {
385                    #[inline]
386                    fn borrow(&self) -> &[u8] {
387                        ::core::borrow::Borrow::<[u8]>::borrow(&self.#field)
388                    }
389                }
390            },
391            Wrapper::Index => {
392                let where_clause = match where_clause {
393                    None => quote! { where },
394                    Some(_) => quote! { #where_clause },
395                };
396                quote! {
397                    #[automatically_derived]
398                    impl <#impl_generics_params> ::core::ops::Index<usize> for #ident_name #ty_generics #where_clause
399                    {
400                        type Output = <#from as ::core::ops::Index<usize>>::Output;
401
402                        #[inline]
403                        fn index(&self, index: usize) -> &Self::Output {
404                            self.#field.index(index)
405                        }
406                    }
407                }
408            }
409            Wrapper::IndexRange => {
410                quote! {
411                    #[automatically_derived]
412                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::Range<usize>> for #ident_name #ty_generics #where_clause
413                    {
414                        type Output = <#from as ::core::ops::Index<::core::ops::Range<usize>>>::Output;
415
416                        #[inline]
417                        fn index(&self, index: ::core::ops::Range<usize>) -> &Self::Output {
418                            self.#field.index(index)
419                        }
420                    }
421                }
422            }
423            Wrapper::IndexFrom => {
424                quote! {
425                    #[automatically_derived]
426                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::RangeFrom<usize>> for #ident_name #ty_generics #where_clause
427                    {
428                        type Output = <#from as ::core::ops::Index<::core::ops::RangeFrom<usize>>>::Output;
429
430                        #[inline]
431                        fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &Self::Output {
432                            self.#field.index(index)
433                        }
434                    }
435                }
436            }
437            Wrapper::IndexTo => {
438                quote! {
439                    #[automatically_derived]
440                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::RangeTo<usize>> for #ident_name #ty_generics #where_clause
441                    {
442                        type Output = <#from as ::core::ops::Index<::core::ops::RangeTo<usize>>>::Output;
443
444                        #[inline]
445                        fn index(&self, index: ::core::ops::RangeTo<usize>) -> &Self::Output {
446                            self.#field.index(index)
447                        }
448                    }
449                }
450            }
451            Wrapper::IndexInclusive => {
452                quote! {
453                    #[automatically_derived]
454                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::RangeInclusive<usize>> for #ident_name #ty_generics #where_clause
455                    {
456                        type Output = <#from as ::core::ops::Index<::core::ops::RangeInclusive<usize>>>::Output;
457
458                        #[inline]
459                        fn index(&self, index: ::core::ops::RangeInclusive<usize>) -> &Self::Output {
460                            self.#field.index(index)
461                        }
462                    }
463                }
464            }
465            Wrapper::IndexToInclusive => {
466                quote! {
467                    #[automatically_derived]
468                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::RangeToInclusive<usize>> for #ident_name #ty_generics #where_clause
469                    {
470                        type Output = <#from as ::core::ops::Index<::core::ops::RangeInclusive<usize>>>::Output;
471
472                        #[inline]
473                        fn index(&self, index: ::core::ops::RangeToInclusive<usize>) -> &Self::Output {
474                            self.#field.index(index)
475                        }
476                    }
477                }
478            }
479            Wrapper::IndexFull => {
480                quote! {
481                    #[automatically_derived]
482                    impl <#impl_generics_params> ::core::ops::Index<::core::ops::RangeFull> for #ident_name #ty_generics #where_clause
483                    {
484                        type Output = <#from as ::core::ops::Index<::core::ops::RangeFull>>::Output;
485
486                        #[inline]
487                        fn index(&self, index: ::core::ops::RangeFull) -> &Self::Output {
488                            self.#field.index(index)
489                        }
490                    }
491                }
492            }
493            Wrapper::Neg => quote! {
494                #[automatically_derived]
495                impl #impl_generics ::core::ops::Neg for #ident_name #ty_generics #where_clause
496                {
497                    type Output = Self;
498
499                    #[inline]
500                    fn neg(self) -> Self {
501                        Self { #field: ::core::ops::Neg::neg(self.#field) }
502                    }
503                }
504            },
505            Wrapper::Not => quote! {
506                #[automatically_derived]
507                impl #impl_generics ::core::ops::Not for #ident_name #ty_generics #where_clause
508                {
509                    type Output = Self;
510
511                    #[inline]
512                    fn not(self) -> Self {
513                        Self { #field: ::core::ops::Not::not(self.#field) }
514                    }
515                }
516            },
517            Wrapper::Add => quote! {
518                #[automatically_derived]
519                impl #impl_generics ::core::ops::Add for #ident_name #ty_generics #where_clause
520                {
521                    type Output = Self;
522
523                    #[inline]
524                    fn add(self, rhs: Self) -> Self {
525                        Self { #field: ::core::ops::Add::add(self.#field, rhs.#field) }
526                    }
527                }
528            },
529            Wrapper::Sub => quote! {
530                #[automatically_derived]
531                impl #impl_generics ::core::ops::Sub for #ident_name #ty_generics #where_clause
532                {
533                    type Output = Self;
534
535                    #[inline]
536                    fn sub(self, rhs: Self) -> Self {
537                        Self { #field: ::core::ops::Sub::sub(self.#field, rhs.#field) }
538                    }
539                }
540            },
541            Wrapper::Mul => quote! {
542                #[automatically_derived]
543                impl #impl_generics ::core::ops::Mul for #ident_name #ty_generics #where_clause
544                {
545                    type Output = Self;
546
547                    #[inline]
548                    fn mul(self, rhs: Self) -> Self {
549                        Self { #field: ::core::ops::Mul::mul(self.#field, rhs.#field) }
550                    }
551                }
552            },
553            Wrapper::Div => quote! {
554                #[automatically_derived]
555                impl #impl_generics ::core::ops::Div for #ident_name #ty_generics #where_clause
556                {
557                    type Output = Self;
558
559                    #[inline]
560                    fn div(self, rhs: Self) -> Self {
561                        Self { #field: ::core::ops::Div::div(self.#field, rhs.#field) }
562                    }
563                }
564            },
565            Wrapper::Rem => quote! {
566                #[automatically_derived]
567                impl #impl_generics ::core::ops::Rem for #ident_name #ty_generics #where_clause
568                {
569                    type Output = Self;
570
571                    #[inline]
572                    fn rem(self, rhs: Self) -> Self {
573                        Self { #field: ::core::ops::Rem::rem(self.#field, rhs.#field) }
574                    }
575                }
576            },
577            Wrapper::Shl => quote! {
578                #[automatically_derived]
579                impl #impl_generics ::core::ops::Shl for #ident_name #ty_generics #where_clause
580                {
581                    type Output = Self;
582
583                    #[inline]
584                    fn shl(self, rhs: Self) -> Self {
585                        Self { #field: ::core::ops::Shl::shl(self.#field, rhs.#field) }
586                    }
587                }
588            },
589            Wrapper::Shr => quote! {
590                #[automatically_derived]
591                impl #impl_generics ::core::ops::Shr for #ident_name #ty_generics #where_clause
592                {
593                    type Output = Self;
594
595                    #[inline]
596                    fn shr(self, rhs: Self) -> Self {
597                        Self { #field: ::core::ops::Shr::shr(self.#field, rhs.#field) }
598                    }
599                }
600            },
601            Wrapper::BitAnd => quote! {
602                #[automatically_derived]
603                impl #impl_generics ::core::ops::BitAnd for #ident_name #ty_generics #where_clause
604                {
605                    type Output = Self;
606
607                    #[inline]
608                    fn bitand(self, rhs: Self) -> Self {
609                        Self { #field: ::core::ops::BitAnd::bitand(self.#field, rhs.#field) }
610                    }
611                }
612            },
613            Wrapper::BitOr => quote! {
614                #[automatically_derived]
615                impl #impl_generics ::core::ops::BitOr for #ident_name #ty_generics #where_clause
616                {
617                    type Output = Self;
618
619                    #[inline]
620                    fn bitor(self, rhs: Self) -> Self {
621                        Self { #field: ::core::ops::BitOr::bitor(self.#field, rhs.#field) }
622                    }
623                }
624            },
625            Wrapper::BitXor => quote! {
626                #[automatically_derived]
627                impl #impl_generics ::core::ops::BitXor for #ident_name #ty_generics #where_clause
628                {
629                    type Output = Self;
630
631                    #[inline]
632                    fn bitxor(self, rhs: Self) -> Self {
633                        Self { #field: ::core::ops::BitXor::bitxor(self.#field, rhs.#field) }
634                    }
635                }
636            },
637            Wrapper::NoRefs |
638            Wrapper::Hex |
639            Wrapper::Exp |
640            Wrapper::NumberFmt |
641            Wrapper::RangeOps |
642            Wrapper::MathOps |
643            Wrapper::BoolOps |
644            Wrapper::BitOps => unreachable!(),
645        }
646    }
647}
648
649impl FromPath for WrapperMut {
650    const IDENT: &'static str = "wrapper_mut";
651    const NO_REFS: Self = Self::NoRefs;
652
653    fn default_set() -> Vec<Self> { vec![WrapperMut::AsMut, WrapperMut::BorrowMut] }
654
655    fn is_not_ref(&self) -> bool { *self != WrapperMut::AsMut && *self != WrapperMut::BorrowMut }
656
657    fn from_path(path: &Path) -> Result<Option<Self>> {
658        path.segments.first().map_or(
659            Err(attr_err!(path.span(), NAME, "must contain at least one identifier", EXAMPLE)),
660            |segment| {
661                Ok(match segment.ident.to_string().as_str() {
662                    "NoRefs" => Some(WrapperMut::NoRefs),
663                    "DerefMut" => Some(WrapperMut::DerefMut),
664                    "AsMut" => Some(WrapperMut::AsMut),
665                    "AsSliceMut" => Some(WrapperMut::AsSliceMut),
666                    "BorrowMut" => Some(WrapperMut::BorrowMut),
667                    "BorrowSliceMut" => Some(WrapperMut::BorrowSliceMut),
668                    "IndexMut" => Some(WrapperMut::IndexMut),
669                    "IndexRangeMut" => Some(WrapperMut::IndexRangeMut),
670                    "IndexFullMut" => Some(WrapperMut::IndexFullMut),
671                    "IndexFromMut" => Some(WrapperMut::IndexFromMut),
672                    "IndexToMut" => Some(WrapperMut::IndexToMut),
673                    "IndexInclusiveMut" => Some(WrapperMut::IndexInclusiveMut),
674                    "IndexToInclusiveMut" => Some(WrapperMut::IndexToInclusiveMut),
675                    "AddAssign" => Some(WrapperMut::AddAssign),
676                    "SubAssign" => Some(WrapperMut::SubAssign),
677                    "MulAssign" => Some(WrapperMut::MulAssign),
678                    "DivAssign" => Some(WrapperMut::DivAssign),
679                    "RemAssign" => Some(WrapperMut::RemAssign),
680                    "ShlAssign" => Some(WrapperMut::ShlAssign),
681                    "ShrAssign" => Some(WrapperMut::ShrAssign),
682                    "BitAndAssign" => Some(WrapperMut::BitAndAssign),
683                    "BitOrAssign" => Some(WrapperMut::BitOrAssign),
684                    "BitXorAssign" => Some(WrapperMut::BitXorAssign),
685
686                    "RangeMut" => Some(WrapperMut::RangeMut),
687                    "MathAssign" => Some(WrapperMut::MathAssign),
688                    "BoolAssign" => Some(WrapperMut::BoolAssign),
689                    "BitAssign" => Some(WrapperMut::BitAssign),
690                    _ => None,
691                })
692            },
693        )
694    }
695
696    fn populate(self, list: &mut Vec<Self>) {
697        let exp = match self {
698            WrapperMut::RangeMut => &[
699                WrapperMut::IndexRangeMut,
700                WrapperMut::IndexFromMut,
701                WrapperMut::IndexToMut,
702                WrapperMut::IndexInclusiveMut,
703                WrapperMut::IndexToInclusiveMut,
704                WrapperMut::IndexFullMut,
705            ] as &[_],
706            WrapperMut::MathAssign => &[
707                WrapperMut::AddAssign,
708                WrapperMut::SubAssign,
709                WrapperMut::MulAssign,
710                WrapperMut::DivAssign,
711                WrapperMut::RemAssign,
712            ] as &[_],
713            WrapperMut::BoolAssign => {
714                &[WrapperMut::BitAndAssign, WrapperMut::BitOrAssign, WrapperMut::BitXorAssign]
715                    as &[_]
716            }
717            WrapperMut::BitAssign => &[
718                WrapperMut::BitAndAssign,
719                WrapperMut::BitOrAssign,
720                WrapperMut::BitXorAssign,
721                WrapperMut::ShlAssign,
722                WrapperMut::ShrAssign,
723            ],
724            x => {
725                list.push(x);
726                &[] as &[_]
727            }
728        };
729        list.extend(exp)
730    }
731}
732
733impl WrapperMut {
734    pub fn into_token_stream2(
735        self,
736        input: &DeriveInput,
737        _from: &Type,
738        field: &TokenStream2,
739    ) -> TokenStream2 {
740        let impl_generics_params = input.generics.params.clone();
741        let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
742        let ident_name = &input.ident;
743        let amplify_crate = get_amplify_crate(input);
744
745        match self {
746            WrapperMut::DerefMut => quote! {
747                #[automatically_derived]
748                impl #impl_generics ::core::ops::DerefMut for #ident_name #ty_generics #where_clause
749                {
750                    #[inline]
751                    fn deref_mut(&mut self) -> &mut Self::Target {
752                        &mut self.#field
753                    }
754                }
755            },
756            WrapperMut::AsMut => quote! {
757                #[automatically_derived]
758                impl #impl_generics ::core::convert::AsMut<<#ident_name #impl_generics as #amplify_crate::Wrapper>::Inner> for #ident_name #ty_generics #where_clause {
759                    #[inline]
760                    fn as_mut(&mut self) -> &mut <Self as #amplify_crate::Wrapper>::Inner {
761                        &mut self.#field
762                    }
763                }
764            },
765            WrapperMut::AsSliceMut => quote! {
766                #[automatically_derived]
767                impl #impl_generics AsMut<[u8]> for #ident_name #ty_generics #where_clause
768                {
769                    #[inline]
770                    fn as_mut(&mut self) -> &mut [u8] {
771                        AsMut::<[u8]>::as_mut(&mut self.#field)
772                    }
773                }
774            },
775            WrapperMut::BorrowMut => quote! {
776                #[automatically_derived]
777                impl #impl_generics ::core::borrow::BorrowMut<<#ident_name #impl_generics as #amplify_crate::Wrapper>::Inner> for #ident_name #ty_generics #where_clause {
778                    #[inline]
779                    fn borrow_mut(&mut self) -> &mut <Self as #amplify_crate::Wrapper>::Inner {
780                        &mut self.#field
781                    }
782                }
783            },
784            WrapperMut::BorrowSliceMut => quote! {
785                #[automatically_derived]
786                impl #impl_generics ::core::borrow::BorrowMut<[u8]> for #ident_name #ty_generics #where_clause
787                {
788                    #[inline]
789                    fn borrow_mut(&mut self) -> &mut [u8] {
790                        ::core::borrow::BorrowMut::<[u8]>::borrow_mut(&mut self.#field)
791                    }
792                }
793            },
794            WrapperMut::IndexMut => {
795                let where_clause = match where_clause {
796                    None => quote! { where },
797                    Some(_) => quote! { #where_clause },
798                };
799                quote! {
800                    #[automatically_derived]
801                    impl <#impl_generics_params> ::core::ops::IndexMut<usize> for #ident_name #ty_generics #where_clause
802                    {
803                        #[inline]
804                        fn index_mut(&mut self, index: usize) -> &mut Self::Output {
805                            self.as_mut().index_mut(index)
806                        }
807                    }
808                }
809            }
810            WrapperMut::IndexRangeMut => {
811                quote! {
812                    #[automatically_derived]
813                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::Range<usize>> for #ident_name #ty_generics #where_clause
814                    {
815                        #[inline]
816                        fn index_mut(&mut self, index: ::core::ops::Range<usize>) -> &mut Self::Output {
817                            self.as_mut().index_mut(index)
818                        }
819                    }
820                }
821            }
822            WrapperMut::IndexFromMut => {
823                quote! {
824                    #[automatically_derived]
825                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::RangeFrom<usize>> for #ident_name #ty_generics #where_clause
826                    {
827                        #[inline]
828                        fn index_mut(&mut self, index: ::core::ops::RangeFrom<usize>) -> &mut Self::Output {
829                            self.as_mut().index_mut(index)
830                        }
831                    }
832                }
833            }
834            WrapperMut::IndexToMut => {
835                quote! {
836                    #[automatically_derived]
837                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::RangeTo<usize>> for #ident_name #ty_generics #where_clause
838                    {
839                        #[inline]
840                        fn index_mut(&mut self, index: ::core::ops::RangeTo<usize>) -> &mut Self::Output {
841                            self.as_mut().index_mut(index)
842                        }
843                    }
844                }
845            }
846            WrapperMut::IndexInclusiveMut => {
847                quote! {
848                    #[automatically_derived]
849                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::RangeInclusive<usize>> for #ident_name #ty_generics #where_clause
850                    {
851                        #[inline]
852                        fn index_mut(&mut self, index: ::core::ops::RangeInclusive<usize>) -> &mut Self::Output {
853                            self.as_mut().index_mut(index)
854                        }
855                    }
856                }
857            }
858            WrapperMut::IndexToInclusiveMut => {
859                quote! {
860                    #[automatically_derived]
861                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::RangeToInclusive<usize>> for #ident_name #ty_generics #where_clause
862                    {
863                        #[inline]
864                        fn index_mut(&mut self, index: ::core::ops::RangeToInclusive<usize>) -> &mut Self::Output {
865                            self.as_mut().index_mut(index)
866                        }
867                    }
868                }
869            }
870            WrapperMut::IndexFullMut => {
871                quote! {
872                    #[automatically_derived]
873                    impl <#impl_generics_params> ::core::ops::IndexMut<::core::ops::RangeFull> for #ident_name #ty_generics #where_clause
874                    {
875                        #[inline]
876                        fn index_mut(&mut self, index: ::core::ops::RangeFull) -> &mut Self::Output {
877                            self.as_mut().index_mut(index)
878                        }
879                    }
880                }
881            }
882            WrapperMut::AddAssign => quote! {
883                #[automatically_derived]
884                impl #impl_generics ::core::ops::AddAssign for #ident_name #ty_generics #where_clause
885                {
886                    #[inline]
887                    fn add_assign(&mut self, rhs: Self) {
888                        ::core::ops::AddAssign::add_assign(&mut self.#field, rhs.#field)
889                    }
890                }
891            },
892            WrapperMut::SubAssign => quote! {
893                #[automatically_derived]
894                impl #impl_generics ::core::ops::SubAssign for #ident_name #ty_generics #where_clause
895                {
896                    #[inline]
897                    fn sub_assign(&mut self, rhs: Self) {
898                        ::core::ops::SubAssign::sub_assign(&mut self.#field, rhs.#field)
899                    }
900                }
901            },
902            WrapperMut::MulAssign => quote! {
903                #[automatically_derived]
904                impl #impl_generics ::core::ops::MulAssign for #ident_name #ty_generics #where_clause
905                {
906                    #[inline]
907                    fn mul_assign(&mut self, rhs: Self) {
908                        ::core::ops::MulAssign::mul_assign(&mut self.#field, rhs.#field)
909                    }
910                }
911            },
912            WrapperMut::DivAssign => quote! {
913                #[automatically_derived]
914                impl #impl_generics ::core::ops::DivAssign for #ident_name #ty_generics #where_clause
915                {
916                    #[inline]
917                    fn div_assign(&mut self, rhs: Self) {
918                        ::core::ops::DivAssign::div_assign(&mut self.#field, rhs.#field)
919                    }
920                }
921            },
922            WrapperMut::RemAssign => quote! {
923                #[automatically_derived]
924                impl #impl_generics ::core::ops::RemAssign for #ident_name #ty_generics #where_clause
925                {
926                    #[inline]
927                    fn rem_assign(&mut self, rhs: Self) {
928                        ::core::ops::RemAssign::rem_assign(&mut self.#field, rhs.#field)
929                    }
930                }
931            },
932            WrapperMut::ShlAssign => quote! {
933                #[automatically_derived]
934                impl #impl_generics ::core::ops::ShlAssign for #ident_name #ty_generics #where_clause
935                {
936                    #[inline]
937                    fn shl_assign(&mut self, rhs: Self) {
938                        ::core::ops::ShlAssign::shl_assign(&mut self.#field, rhs.#field)
939                    }
940                }
941            },
942            WrapperMut::ShrAssign => quote! {
943                #[automatically_derived]
944                impl #impl_generics ::core::ops::ShrAssign for #ident_name #ty_generics #where_clause
945                {
946                    #[inline]
947                    fn shr_assign(&mut self, rhs: Self) {
948                        ::core::ops::ShrAssign::shr_assign(&mut self.#field, rhs.#field)
949                    }
950                }
951            },
952            WrapperMut::BitAndAssign => quote! {
953                #[automatically_derived]
954                impl #impl_generics ::core::ops::BitAndAssign for #ident_name #ty_generics #where_clause
955                {
956                    #[inline]
957                    fn bitand_assign(&mut self, rhs: Self) {
958                        ::core::ops::BitAndAssign::bitand_assign(&mut self.#field, rhs.#field)
959                    }
960                }
961            },
962            WrapperMut::BitOrAssign => quote! {
963                #[automatically_derived]
964                impl #impl_generics ::core::ops::BitOrAssign for #ident_name #ty_generics #where_clause
965                {
966                    #[inline]
967                    fn bitor_assign(&mut self, rhs: Self) {
968                        ::core::ops::BitOrAssign::bitor_assign(&mut self.#field, rhs.#field)
969                    }
970                }
971            },
972            WrapperMut::BitXorAssign => quote! {
973                #[automatically_derived]
974                impl #impl_generics ::core::ops::BitXorAssign for #ident_name #ty_generics #where_clause
975                {
976                    #[inline]
977                    fn bitxor_assign(&mut self, rhs: Self) {
978                        ::core::ops::BitXorAssign::bitxor_assign(&mut self.#field, rhs.#field)
979                    }
980                }
981            },
982            WrapperMut::NoRefs |
983            WrapperMut::RangeMut |
984            WrapperMut::MathAssign |
985            WrapperMut::BoolAssign |
986            WrapperMut::BitAssign => unreachable!(),
987        }
988    }
989}
990
991pub(crate) fn inner(input: DeriveInput) -> Result<TokenStream2> {
992    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
993    let ident_name = &input.ident;
994    let amplify_crate = get_amplify_crate(&input);
995
996    let (field, from) = get_params(&input)?;
997
998    let wrappers = get_wrappers::<Wrapper>(&input)?;
999    let wrapper_derive = wrappers
1000        .iter()
1001        .map(|w| w.into_token_stream2(&input, &from, &field));
1002
1003    Ok(quote! {
1004        #[automatically_derived]
1005        impl #impl_generics #amplify_crate::Wrapper for #ident_name #ty_generics #where_clause {
1006            type Inner = #from;
1007
1008            #[inline]
1009            fn from_inner(inner: Self::Inner) -> Self {
1010                Self::from(inner)
1011            }
1012
1013            #[inline]
1014            fn as_inner(&self) -> &Self::Inner {
1015                &self.#field
1016            }
1017
1018            #[inline]
1019            fn into_inner(self) -> Self::Inner {
1020                self.#field
1021            }
1022        }
1023
1024        #[automatically_derived]
1025        impl #impl_generics ::core::convert::From<#ident_name #ty_generics> for #from #where_clause {
1026            #[inline]
1027            fn from(wrapped: #ident_name #ty_generics) -> Self {
1028                wrapped.#field
1029            }
1030        }
1031
1032        #( #wrapper_derive )*
1033    })
1034}
1035
1036pub(crate) fn inner_mut(input: DeriveInput) -> Result<TokenStream2> {
1037    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
1038    let ident_name = &input.ident;
1039    let amplify_crate = get_amplify_crate(&input);
1040
1041    let (field, from) = get_params(&input)?;
1042
1043    let wrappers = get_wrappers::<WrapperMut>(&input)?;
1044    let wrapper_derive = wrappers
1045        .iter()
1046        .map(|w| w.into_token_stream2(&input, &from, &field));
1047
1048    Ok(quote! {
1049        #[automatically_derived]
1050        impl #impl_generics #amplify_crate::WrapperMut for #ident_name #ty_generics #where_clause {
1051            #[inline]
1052            fn as_inner_mut(&mut self) -> &mut <Self as #amplify_crate::Wrapper>::Inner {
1053                &mut self.#field
1054            }
1055        }
1056
1057        #( #wrapper_derive )*
1058    })
1059}
1060
1061fn get_params(input: &DeriveInput) -> Result<(TokenStream2, Type)> {
1062    let data = match input.data {
1063        Data::Struct(ref data) => data,
1064        Data::Enum(_) => {
1065            return Err(Error::new_spanned(input, "Deriving wrapper is not supported in enums"));
1066        }
1067        //strict_encode_inner_enum(&input, &data),
1068        Data::Union(_) => {
1069            return Err(Error::new_spanned(input, "Deriving wrapper is not supported in unions"));
1070        }
1071    };
1072
1073    let field;
1074    let mut from;
1075    match data.fields {
1076        Fields::Named(ref fields) => {
1077            let mut source = None;
1078            from = fields.named[0].ty.clone();
1079            for field in &fields.named {
1080                for attr in &field.attrs {
1081                    if attr.path.is_ident("wrap") {
1082                        if source.is_some() {
1083                            return Err(Error::new_spanned(
1084                                attr,
1085                                "Only a single field may be wrapped",
1086                            ));
1087                        }
1088                        source = Some(field.ident.clone().expect("we know it's named"));
1089                        from = field.ty.clone();
1090                    }
1091                }
1092            }
1093            if source.is_none() && fields.named.len() > 1 {
1094                return Err(Error::new_spanned(
1095                    fields,
1096                    "When the structure has multiple fields you must point out the one you will \
1097                     wrap by using `#[wrap]` attribute",
1098                ));
1099            }
1100            let source = source
1101                .unwrap_or_else(|| fields.named[0].ident.clone().expect("we know it's named"));
1102            field = quote! { #source };
1103        }
1104        Fields::Unnamed(ref fields) => {
1105            let mut source = None;
1106            from = fields.unnamed[0].ty.clone();
1107            for (index, field) in fields.unnamed.iter().enumerate() {
1108                for attr in &field.attrs {
1109                    if attr.path.is_ident("wrap") {
1110                        if source.is_some() {
1111                            return Err(Error::new_spanned(
1112                                attr,
1113                                "Only a single field may be wrapped",
1114                            ));
1115                        }
1116                        let i = Index::from(index);
1117                        source = Some(quote! { #i });
1118                        from = field.ty.clone();
1119                    }
1120                }
1121            }
1122            if source.is_none() && fields.unnamed.len() > 1 {
1123                return Err(Error::new_spanned(
1124                    fields,
1125                    "When the structure has multiple fields you must point out the one you will \
1126                     wrap by using `#[wrap]` attribute",
1127                ));
1128            }
1129            field = source.unwrap_or(quote! { 0 });
1130        }
1131        Fields::Unit => {
1132            return Err(Error::new_spanned(
1133                input,
1134                "Deriving wrapper is meaningless for unit structs",
1135            ));
1136        }
1137    };
1138    Ok((field, from))
1139}
1140
1141fn get_wrappers<T: FromPath>(input: &DeriveInput) -> Result<Vec<T>> {
1142    let mut wrappers = T::default_set();
1143    const WRAPPER_DERIVE_ERR: &str = "Wrapper attributes must be in a form of type list";
1144    for attr in input
1145        .attrs
1146        .iter()
1147        .filter(|attr| attr.path.is_ident(T::IDENT))
1148    {
1149        match attr
1150            .parse_meta()
1151            .map_err(|_| attr_err!(attr, WRAPPER_DERIVE_ERR))?
1152        {
1153            Meta::List(MetaList { nested, .. }) => {
1154                for meta in nested {
1155                    match meta {
1156                        NestedMeta::Meta(Meta::Path(path)) => {
1157                            T::from_path(&path)?
1158                                .ok_or_else(|| attr_err!(path, "Unrecognized wrapper parameter"))?
1159                                .populate(&mut wrappers);
1160                        }
1161                        _ => return Err(attr_err!(meta, WRAPPER_DERIVE_ERR)),
1162                    }
1163                }
1164            }
1165            _ => return Err(attr_err!(attr, WRAPPER_DERIVE_ERR)),
1166        }
1167    }
1168    if wrappers.contains(&T::NO_REFS) {
1169        wrappers = wrappers.into_iter().filter(T::is_not_ref).collect();
1170    }
1171    Ok(wrappers)
1172}