1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | |
3 | #[cfg (feature = "ops" )] |
4 | pub(crate) mod deref { |
5 | use crate::derive::*; |
6 | |
7 | pub(crate) const NAME: &[&str] = &["Deref" ]; |
8 | |
9 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
10 | Ok(derive_trait(data, &parse_quote!(::core::ops::Deref), None, parse_quote! { |
11 | trait Deref { |
12 | type Target; |
13 | #[inline] |
14 | fn deref(&self) -> &Self::Target; |
15 | } |
16 | })) |
17 | } |
18 | } |
19 | |
20 | #[cfg (feature = "ops" )] |
21 | pub(crate) mod deref_mut { |
22 | use crate::derive::*; |
23 | |
24 | pub(crate) const NAME: &[&str] = &["DerefMut" ]; |
25 | |
26 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
27 | Ok(derive_trait( |
28 | data, |
29 | &parse_quote!(::core::ops::DerefMut), |
30 | Some(format_ident!("Target" )), |
31 | parse_quote! { |
32 | trait DerefMut: ::core::ops::Deref { |
33 | #[inline] |
34 | fn deref_mut(&mut self) -> &mut Self::Target; |
35 | } |
36 | }, |
37 | )) |
38 | } |
39 | } |
40 | |
41 | #[cfg (feature = "ops" )] |
42 | pub(crate) mod index { |
43 | use crate::derive::*; |
44 | |
45 | pub(crate) const NAME: &[&str] = &["Index" ]; |
46 | |
47 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
48 | Ok(derive_trait(data, &parse_quote!(::core::ops::Index), None, parse_quote! { |
49 | trait Index<__Idx> { |
50 | type Output; |
51 | #[inline] |
52 | fn index(&self, index: __Idx) -> &Self::Output; |
53 | } |
54 | })) |
55 | } |
56 | } |
57 | |
58 | #[cfg (feature = "ops" )] |
59 | pub(crate) mod index_mut { |
60 | use crate::derive::*; |
61 | |
62 | pub(crate) const NAME: &[&str] = &["IndexMut" ]; |
63 | |
64 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
65 | Ok(derive_trait( |
66 | data, |
67 | &parse_quote!(::core::ops::IndexMut), |
68 | Some(format_ident!("Output" )), |
69 | parse_quote! { |
70 | trait IndexMut<__Idx>: ::core::ops::Index<__Idx> { |
71 | #[inline] |
72 | fn index_mut(&mut self, index: __Idx) -> &mut Self::Output; |
73 | } |
74 | }, |
75 | )) |
76 | } |
77 | } |
78 | |
79 | #[cfg (feature = "ops" )] |
80 | pub(crate) mod range_bounds { |
81 | use crate::derive::*; |
82 | |
83 | pub(crate) const NAME: &[&str] = &["RangeBounds" ]; |
84 | |
85 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
86 | Ok(derive_trait(data, &parse_quote!(::core::ops::RangeBounds), None, parse_quote! { |
87 | trait RangeBounds<__T: ?Sized> { |
88 | #[inline] |
89 | fn start_bound(&self) -> ::core::ops::Bound<&__T>; |
90 | #[inline] |
91 | fn end_bound(&self) -> ::core::ops::Bound<&__T>; |
92 | } |
93 | })) |
94 | } |
95 | } |
96 | |
97 | #[cfg (feature = "coroutine_trait" )] |
98 | pub(crate) mod coroutine { |
99 | use quote::ToTokens; |
100 | |
101 | use crate::derive::*; |
102 | |
103 | pub(crate) const NAME: &[&str] = &["Coroutine" ]; |
104 | |
105 | pub(crate) fn derive(cx: &Context, data: &Data) -> Result<TokenStream> { |
106 | cx.needs_pin_projection(); |
107 | |
108 | let ident = &data.ident; |
109 | let pin = quote!(::core::pin::Pin); |
110 | let trait_ = parse_quote!(::core::ops::Coroutine); |
111 | let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { |
112 | trait Coroutine<R> { |
113 | type Yield; |
114 | type Return; |
115 | } |
116 | }) |
117 | .build_impl(); |
118 | |
119 | let resume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { |
120 | quote! { |
121 | #ident::#v(x) => <#ty as #trait_<R>>::resume(#pin::new_unchecked(x), arg), |
122 | } |
123 | }); |
124 | impl_.items.push(parse_quote! { |
125 | #[inline] |
126 | fn resume( |
127 | self: #pin<&mut Self>, |
128 | arg: R, |
129 | ) -> ::core::ops::CoroutineState<Self::Yield, Self::Return> { |
130 | unsafe { |
131 | match self.get_unchecked_mut() { #(#resume)* } |
132 | } |
133 | } |
134 | }); |
135 | |
136 | Ok(impl_.into_token_stream()) |
137 | } |
138 | } |
139 | |
140 | #[cfg (feature = "fn_traits" )] |
141 | pub(crate) mod fn_ { |
142 | use derive_utils::EnumImpl; |
143 | use syn::TypeParam; |
144 | |
145 | use crate::derive::*; |
146 | |
147 | pub(crate) const NAME: &[&str] = &["Fn" ]; |
148 | |
149 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
150 | let trait_path = quote!(::core::ops::Fn); |
151 | let trait_ = quote!(#trait_path(__T) -> __U); |
152 | let mut impl_ = EnumImpl::new(data); |
153 | |
154 | impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); |
155 | impl_.push_generic_param(TypeParam::from(format_ident!("__T" )).into()); |
156 | impl_.push_generic_param(TypeParam::from(format_ident!("__U" )).into()); |
157 | |
158 | data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); |
159 | |
160 | impl_.push_method(parse_quote! { |
161 | #[inline] |
162 | extern "rust-call" fn call(&self, args: (__T,)) -> Self::Output; |
163 | }); |
164 | |
165 | Ok(impl_.build()) |
166 | } |
167 | } |
168 | |
169 | #[cfg (feature = "fn_traits" )] |
170 | pub(crate) mod fn_mut { |
171 | use derive_utils::EnumImpl; |
172 | use syn::TypeParam; |
173 | |
174 | use crate::derive::*; |
175 | |
176 | pub(crate) const NAME: &[&str] = &["FnMut" ]; |
177 | |
178 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
179 | let trait_path = quote!(::core::ops::FnMut); |
180 | let trait_ = quote!(#trait_path(__T) -> __U); |
181 | let mut impl_ = EnumImpl::new(data); |
182 | |
183 | impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); |
184 | impl_.push_generic_param(TypeParam::from(format_ident!("__T" )).into()); |
185 | impl_.push_generic_param(TypeParam::from(format_ident!("__U" )).into()); |
186 | |
187 | data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); |
188 | |
189 | impl_.push_method(parse_quote! { |
190 | #[inline] |
191 | extern "rust-call" fn call_mut(&mut self, args: (__T,)) -> Self::Output; |
192 | }); |
193 | |
194 | Ok(impl_.build()) |
195 | } |
196 | } |
197 | |
198 | #[cfg (feature = "fn_traits" )] |
199 | pub(crate) mod fn_once { |
200 | use derive_utils::EnumImpl; |
201 | use syn::TypeParam; |
202 | |
203 | use crate::derive::*; |
204 | |
205 | pub(crate) const NAME: &[&str] = &["FnOnce" ]; |
206 | |
207 | pub(crate) fn derive(_cx: &Context, data: &Data) -> Result<TokenStream> { |
208 | let trait_path = quote!(::core::ops::FnOnce); |
209 | let trait_ = quote!(#trait_path(__T) -> __U); |
210 | let mut impl_ = EnumImpl::new(data); |
211 | |
212 | impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); |
213 | impl_.push_generic_param(TypeParam::from(format_ident!("__T" )).into()); |
214 | impl_.push_generic_param(TypeParam::from(format_ident!("__U" )).into()); |
215 | |
216 | data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); |
217 | |
218 | impl_.append_items_from_trait(parse_quote! { |
219 | trait FnOnce { |
220 | type Output; |
221 | #[inline] |
222 | extern "rust-call" fn call_once(self, args: (__T,)) -> Self::Output; |
223 | } |
224 | }); |
225 | |
226 | Ok(impl_.build()) |
227 | } |
228 | } |
229 | |