bare_err_tree_proc/
boiler.rs1use std::iter;
8
9use proc_macro::TokenStream;
10use quote::quote;
11use syn::{Attribute, Generics, Ident, Meta};
12
13pub fn wrapper_boilerplate(
18 ident: &Ident,
19 generics: &Generics,
20 attrs: &[Attribute],
21 name_attribute: &Ident,
22) -> TokenStream {
23 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
24
25 let universal: TokenStream = quote! {
27 #[automatically_derived]
28 impl #impl_generics ::core::error::Error for #name_attribute #ty_generics #where_clause {
29 fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
30 ::core::error::Error::source(&self.inner)
31 }
32 }
33
34 #[automatically_derived]
35 impl #impl_generics ::core::fmt::Debug for #name_attribute #ty_generics #where_clause {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
37 ::core::fmt::Debug::fmt(&self.inner, f)
38 }
39 }
40
41 #[automatically_derived]
42 impl #impl_generics ::core::fmt::Display for #name_attribute #ty_generics #where_clause {
43 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
44 ::core::fmt::Display::fmt(&self.inner, f)
45 }
46 }
47
48 #[automatically_derived]
49 impl #impl_generics ::core::convert::From<#ident #ty_generics> for #name_attribute #ty_generics #where_clause {
50 #[track_caller]
51 fn from(inner: #ident #ty_generics) -> Self {
52 Self::_tree(inner)
53 }
54 }
55
56 #[automatically_derived]
57 impl #impl_generics ::core::convert::From<#name_attribute #ty_generics> for #ident #ty_generics #where_clause {
58 fn from(value: #name_attribute #ty_generics) -> Self {
59 value.inner
60 }
61 }
62
63 #[automatically_derived]
64 impl #impl_generics ::core::ops::Deref for #name_attribute #ty_generics #where_clause {
65 type Target = #ident #ty_generics;
66 fn deref(&self) -> &Self::Target {
67 &self.inner
68 }
69 }
70
71 #[automatically_derived]
72 impl #impl_generics ::core::ops::DerefMut for #name_attribute #ty_generics #where_clause {
73 fn deref_mut(&mut self) -> &mut Self::Target {
74 &mut self.inner
75 }
76 }
77 }
78 .into();
79
80 let mut extra_derive = Vec::new();
82 attrs.iter().for_each(|x| {
83 if let Meta::List(list) = &x.meta {
84 if list.path.get_ident().map(|x| x.to_string()) == Some("derive".to_string()) {
85 let _ = list.parse_nested_meta(|meta| {
86 if let Some(ident) = meta.path.get_ident() {
87 extra_derive.push(ident.clone());
88 }
89 Ok(())
90 });
91 }
92 }
93 });
94
95 let extra_derive_tokens =
97 extra_derive
98 .into_iter()
99 .map(|extra| match extra.to_string().to_lowercase().as_str() {
100 "eq" => quote! {
101 #[automatically_derived]
102 impl #impl_generics ::core::cmp::Eq for #name_attribute #ty_generics #where_clause {}
103 }
104 .into(),
105 "partialeq" => quote! {
106 #[automatically_derived]
107 impl #impl_generics ::core::cmp::PartialEq<#name_attribute #ty_generics> for #name_attribute #ty_generics #where_clause {
108 fn eq(&self, other: &#name_attribute #ty_generics) -> bool {
109 self.inner == other.inner
110 }
111 }
112 }
113 .into(),
114 "ord" => quote! {
115 #[automatically_derived]
116 impl #impl_generics ::core::cmp::Ord for #name_attribute #ty_generics #where_clause {
117 fn ord(&self, other: &Self) -> bool {
118 <#ident #ty_generics #where_clause as ::core::cmp::Ord>::ord(self.inner, other.inner)
119 }
120 }
121 }
122 .into(),
123 "partialord" => quote! {
124 #[automatically_derived]
125 impl #impl_generics ::core::cmp::PartialOrd for #name_attribute #ty_generics #where_clause {
126 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
127 <#ident #ty_generics #where_clause as ::core::cmp::ParitalOrd>::partial_cmp(self.inner, other.inner)
128 }
129 }
130 }
131 .into(),
132 "clone" => quote! {
133 #[automatically_derived]
134 impl #impl_generics ::core::clone::Clone for #name_attribute #ty_generics #where_clause {
135 fn clone(&self) -> Self {
136 Self {
137 inner: self.inner.clone(),
138 _err_tree_pkg: self._err_tree_pkg.clone()
139 }
140 }
141 }
142 }
143 .into(),
144 "hash" => quote! {
145 #[automatically_derived]
146 impl #impl_generics ::core::hash::Hash for #name_attribute #ty_generics #where_clause {
147 fn hash<H>(&self, state: &mut H)
148 where H: ::core::hash::Hasher
149 {
150 self.inner.hash(state)
151 }
152 }
153 }
154 .into(),
155 "default" => quote! {
156 #[automatically_derived]
157 impl #impl_generics ::core::default::Default for #name_attribute #ty_generics #where_clause {
158 #[track_caller]
159 fn default() -> Self {
160 Self {
161 inner: #ident ::default(),
162 _err_tree_pkg: ::bare_err_tree::ErrTreePkg::default(),
163 }
164 }
165 }
166 }
167 .into(),
168 _ => quote! {}.into(),
169 });
170
171 TokenStream::from_iter(iter::once(universal).chain(extra_derive_tokens))
172}