1use proc_macro::TokenStream;
25use proc_macro2::TokenStream as TokenStream2;
26use proc_macro_error::{abort_call_site, proc_macro_error};
27use quote::quote;
28use std::convert::*;
29
30mod common;
31mod entity;
32mod field_type;
33mod holder_attr;
34mod select;
35mod table_init;
36mod type_decl;
37
38use common::*;
39use field_type::*;
40use holder_attr::*;
41use table_init::*;
42
43#[proc_macro_error]
75#[proc_macro_derive(TableInit)]
76pub fn derive_table_init_entry(input: TokenStream) -> TokenStream {
77 derive_table_init(&syn::parse(input).unwrap()).into()
78}
79
80#[proc_macro_error]
82#[proc_macro_derive(Deserialize)]
83pub fn derive_deserialize_entry(input: TokenStream) -> TokenStream {
84 derive_deserialize(&syn::parse(input).unwrap()).into()
85}
86
87fn derive_deserialize(ast: &syn::DeriveInput) -> TokenStream2 {
88 let ident = &ast.ident;
89 match &ast.data {
90 syn::Data::Struct(st) => entity::derive_deserialize(ident, st),
91 syn::Data::Enum(e) => select::derive_deserialize(ident, e),
92 _ => abort_call_site!("Only struct is supprted currently"),
93 }
94}
95
96#[proc_macro_error]
136#[proc_macro_derive(Holder, attributes(holder))]
137pub fn derive_holder_entry(input: TokenStream) -> TokenStream {
138 derive_holder(&syn::parse(input).unwrap()).into()
139}
140
141fn derive_holder(ast: &syn::DeriveInput) -> TokenStream2 {
142 let attr = HolderAttr::parse(&ast.attrs);
143 let ident = &ast.ident;
144 match &ast.data {
145 syn::Data::Struct(st) => match st.fields {
146 syn::Fields::Named(_) => entity::derive_holder(ident, st, &attr),
147 syn::Fields::Unnamed(_) => type_decl::derive_holder(ident, st, &attr),
148 syn::Fields::Unit => abort_call_site!("Unit struct is not supported."),
149 },
150 syn::Data::Enum(e) => select::derive_holder(ident, e, &attr),
151 _ => abort_call_site!("Only struct is supprted currently"),
152 }
153}
154
155#[proc_macro_error]
160#[proc_macro]
161pub fn as_holder(input: TokenStream) -> TokenStream {
162 let path = as_holder_path(&syn::parse(input).unwrap());
163 let ts = quote! { #path };
164 ts.into()
165}
166
167#[cfg(test)]
168mod snapshot_tests {
169 use super::derive_holder;
170
171 #[test]
172 fn derive_holder_enum() {
173 let input: syn::DeriveInput = syn::parse_str(
174 r#"
175 #[holder(table = Table)]
176 #[holder(generate_deserialize)]
177 pub enum S1 {
178 #[holder(use_place_holder)]
179 A(Box<A>),
180 #[holder(use_place_holder)]
181 B(Box<B>),
182 }
183 "#,
184 )
185 .unwrap();
186
187 let tt = derive_holder(&input);
188 let out = espr::codegen::rust::rustfmt(tt.to_string());
189
190 insta::assert_snapshot!(out, @r###"
191 #[doc = r" Auto-generated by `#[derive(Holder)]`"]
192 #[derive(Clone, Debug, PartialEq)]
193 pub enum S1Holder {
194 A(Box<AHolder>),
195 B(Box<BHolder>),
196 }
197 impl ::ruststep::tables::IntoOwned for S1Holder {
198 type Owned = S1;
199 type Table = Table;
200 fn into_owned(self, table: &Self::Table) -> ::ruststep::error::Result<Self::Owned> {
201 Ok(match self {
202 S1Holder::A(sub) => S1::A(Box::new(sub.into_owned(table)?)),
203 S1Holder::B(sub) => S1::B(Box::new(sub.into_owned(table)?)),
204 })
205 }
206 }
207 impl ::ruststep::tables::Holder for S1Holder {
208 fn name() -> &'static str {
209 "S1"
210 }
211 fn attr_len() -> usize {
212 0
213 }
214 }
215 impl<'de> ::ruststep::serde::de::Deserialize<'de> for S1Holder {
216 fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
217 where
218 D: ::ruststep::serde::de::Deserializer<'de>,
219 {
220 deserializer.deserialize_tuple_struct("S1", 0, S1HolderVisitor {})
221 }
222 }
223 #[doc(hidden)]
224 pub struct S1HolderVisitor;
225 impl<'de> ::ruststep::serde::de::Visitor<'de> for S1HolderVisitor {
226 type Value = S1Holder;
227 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
228 write!(formatter, "S1")
229 }
230 fn visit_map<A>(self, mut map: A) -> ::std::result::Result<Self::Value, A::Error>
231 where
232 A: ::ruststep::serde::de::MapAccess<'de>,
233 {
234 let key: String = map
235 .next_key()?
236 .expect("Empty map cannot be accepted as ruststep Holder");
237 match key.as_str() {
238 "A" => {
239 let owned = map.next_value()?;
240 return Ok(S1Holder::A(Box::new(owned)));
241 }
242 "B" => {
243 let owned = map.next_value()?;
244 return Ok(S1Holder::B(Box::new(owned)));
245 }
246 _ => {
247 use ruststep::serde::de::{Error, Unexpected};
248 return Err(A::Error::invalid_value(Unexpected::Other(&key), &self));
249 }
250 }
251 }
252 }
253 impl ::ruststep::tables::WithVisitor for S1Holder {
254 type Visitor = S1HolderVisitor;
255 fn visitor_new() -> Self::Visitor {
256 S1HolderVisitor {}
257 }
258 }
259 impl ::ruststep::tables::EntityTable<S1Holder> for Table {
260 fn get_owned(&self, entity_id: u64) -> ::ruststep::error::Result<S1> {
261 if let Ok(owned) = ::ruststep::tables::EntityTable::<AHolder>::get_owned(self, entity_id) {
262 return Ok(S1::A(Box::new(owned.into())));
263 }
264 if let Ok(owned) = ::ruststep::tables::EntityTable::<BHolder>::get_owned(self, entity_id) {
265 return Ok(S1::B(Box::new(owned.into())));
266 }
267 Err(::ruststep::error::Error::UnknownEntity(entity_id))
268 }
269 fn owned_iter<'table>(
270 &'table self,
271 ) -> Box<dyn Iterator<Item = ::ruststep::error::Result<S1>> + 'table> {
272 Box::new(::ruststep::itertools::chain![
273 ::ruststep::tables::EntityTable::<AHolder>::owned_iter(self)
274 .map(|owned| owned.map(|owned| S1::A(Box::new(owned.into())))),
275 ::ruststep::tables::EntityTable::<BHolder>::owned_iter(self)
276 .map(|owned| owned.map(|owned| S1::B(Box::new(owned.into()))))
277 ])
278 }
279 }
280 "###);
281 }
282
283 #[test]
284 fn derive_holder_enum_any_subsuper() {
285 let input: syn::DeriveInput = syn::parse_str(
286 r#"
287 # [holder (table = Tables)]
288 #[holder(generate_deserialize)]
289 pub enum BaseAny {
290 #[holder(use_place_holder)]
291 # [holder (field = base)]
292 Base(Box<Base>),
293 #[holder(use_place_holder)]
294 # [holder (field = sub)]
295 Sub(Box<SubAny>),
296 }
297 "#,
298 )
299 .unwrap();
300
301 let tt = derive_holder(&input);
302 let out = espr::codegen::rust::rustfmt(tt.to_string());
303
304 insta::assert_snapshot!(out, @r###"
305 #[doc = r" Auto-generated by `#[derive(Holder)]`"]
306 #[derive(Clone, Debug, PartialEq)]
307 pub enum BaseAnyHolder {
308 Base(Box<BaseHolder>),
309 Sub(Box<SubAnyHolder>),
310 }
311 impl ::ruststep::tables::IntoOwned for BaseAnyHolder {
312 type Owned = BaseAny;
313 type Table = Tables;
314 fn into_owned(self, table: &Self::Table) -> ::ruststep::error::Result<Self::Owned> {
315 Ok(match self {
316 BaseAnyHolder::Base(sub) => BaseAny::Base(Box::new(sub.into_owned(table)?)),
317 BaseAnyHolder::Sub(sub) => BaseAny::Sub(Box::new(sub.into_owned(table)?)),
318 })
319 }
320 }
321 impl ::ruststep::tables::Holder for BaseAnyHolder {
322 fn name() -> &'static str {
323 "BASE_ANY"
324 }
325 fn attr_len() -> usize {
326 0
327 }
328 }
329 impl<'de> ::ruststep::serde::de::Deserialize<'de> for BaseAnyHolder {
330 fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
331 where
332 D: ::ruststep::serde::de::Deserializer<'de>,
333 {
334 deserializer.deserialize_tuple_struct("BASE_ANY", 0, BaseAnyHolderVisitor {})
335 }
336 }
337 #[doc(hidden)]
338 pub struct BaseAnyHolderVisitor;
339 impl<'de> ::ruststep::serde::de::Visitor<'de> for BaseAnyHolderVisitor {
340 type Value = BaseAnyHolder;
341 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
342 write!(formatter, "BASE_ANY")
343 }
344 fn visit_map<A>(self, mut map: A) -> ::std::result::Result<Self::Value, A::Error>
345 where
346 A: ::ruststep::serde::de::MapAccess<'de>,
347 {
348 let key: String = map
349 .next_key()?
350 .expect("Empty map cannot be accepted as ruststep Holder");
351 match key.as_str() {
352 "BASE" => {
353 let owned = map.next_value()?;
354 return Ok(BaseAnyHolder::Base(Box::new(owned)));
355 }
356 "SUB" => {
357 let owned = map.next_value()?;
358 return Ok(BaseAnyHolder::Sub(Box::new(owned)));
359 }
360 _ => {
361 use ruststep::serde::de::{Error, Unexpected};
362 return Err(A::Error::invalid_value(Unexpected::Other(&key), &self));
363 }
364 }
365 }
366 }
367 impl ::ruststep::tables::WithVisitor for BaseAnyHolder {
368 type Visitor = BaseAnyHolderVisitor;
369 fn visitor_new() -> Self::Visitor {
370 BaseAnyHolderVisitor {}
371 }
372 }
373 impl ::ruststep::tables::EntityTable<BaseAnyHolder> for Tables {
374 fn get_owned(&self, entity_id: u64) -> ::ruststep::error::Result<BaseAny> {
375 if let Ok(owned) = ::ruststep::tables::EntityTable::<BaseHolder>::get_owned(self, entity_id)
376 {
377 return Ok(BaseAny::Base(Box::new(owned.into())));
378 }
379 if let Ok(owned) =
380 ::ruststep::tables::EntityTable::<SubAnyHolder>::get_owned(self, entity_id)
381 {
382 return Ok(BaseAny::Sub(Box::new(owned.into())));
383 }
384 Err(::ruststep::error::Error::UnknownEntity(entity_id))
385 }
386 fn owned_iter<'table>(
387 &'table self,
388 ) -> Box<dyn Iterator<Item = ::ruststep::error::Result<BaseAny>> + 'table> {
389 Box::new(::ruststep::itertools::chain![
390 ::ruststep::tables::EntityTable::<BaseHolder>::owned_iter(self)
391 .map(|owned| owned.map(|owned| BaseAny::Base(Box::new(owned.into())))),
392 ::ruststep::tables::EntityTable::<SubAnyHolder>::owned_iter(self)
393 .map(|owned| owned.map(|owned| BaseAny::Sub(Box::new(owned.into()))))
394 ])
395 }
396 }
397 "###);
398 }
399
400 #[test]
401 fn skip_unrelated_attributes() {
402 let input: syn::DeriveInput = syn::parse_str(
403 r#"
404 #[derive(
405 Debug, Clone, PartialEq, AsRef, AsMut, Deref, DerefMut, :: derive_new :: new, Holder,
406 )]
407 # [holder (table = Tables)]
408 # [holder (field = sub1)]
409 #[holder(generate_deserialize)]
410 pub struct Sub1 {
411 #[as_ref]
412 #[as_mut]
413 #[deref]
414 #[deref_mut]
415 #[holder(use_place_holder)]
416 pub base: Base,
417 pub y1: f64,
418 }
419 "#,
420 )
421 .unwrap();
422
423 let tt = derive_holder(&input);
424 let out = espr::codegen::rust::rustfmt(tt.to_string());
425
426 insta::assert_snapshot!(out, @r###"
427 #[doc = r" Auto-generated by `#[derive(Holder)]`"]
428 #[derive(Debug, Clone, PartialEq)]
429 pub struct Sub1Holder {
430 pub base: ::ruststep::tables::PlaceHolder<BaseHolder>,
431 pub y1: f64,
432 }
433 #[automatically_derived]
434 impl ::ruststep::tables::IntoOwned for Sub1Holder {
435 type Table = Tables;
436 type Owned = Sub1;
437 fn into_owned(self, table: &Self::Table) -> ::ruststep::error::Result<Self::Owned> {
438 let Sub1Holder { base, y1 } = self;
439 Ok(Sub1 {
440 base: base.into_owned(table)?,
441 y1: y1,
442 })
443 }
444 }
445 #[automatically_derived]
446 impl ::ruststep::tables::Holder for Sub1Holder {
447 fn name() -> &'static str {
448 "SUB_1"
449 }
450 fn attr_len() -> usize {
451 2usize
452 }
453 }
454 #[automatically_derived]
455 impl ::ruststep::tables::EntityTable<Sub1Holder> for Tables {
456 fn get_owned(&self, entity_id: u64) -> ::ruststep::error::Result<Sub1> {
457 ::ruststep::tables::get_owned(self, &self.sub1, entity_id)
458 }
459 fn owned_iter<'table>(
460 &'table self,
461 ) -> Box<dyn Iterator<Item = ::ruststep::error::Result<Sub1>> + 'table> {
462 ::ruststep::tables::owned_iter(self, &self.sub1)
463 }
464 }
465 #[doc(hidden)]
466 pub struct Sub1HolderVisitor;
467 #[automatically_derived]
468 impl<'de> ::ruststep::serde::de::Visitor<'de> for Sub1HolderVisitor {
469 type Value = Sub1Holder;
470 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
471 write!(formatter, "SUB_1")
472 }
473 fn visit_seq<A>(self, mut seq: A) -> ::std::result::Result<Self::Value, A::Error>
474 where
475 A: ::ruststep::serde::de::SeqAccess<'de>,
476 {
477 if let Some(size) = seq.size_hint() {
478 if size != 2usize {
479 use ruststep::serde::de::Error;
480 return Err(A::Error::invalid_length(size, &self));
481 }
482 }
483 let base = seq.next_element()?.unwrap();
484 let y1 = seq.next_element()?.unwrap();
485 Ok(Sub1Holder { base, y1 })
486 }
487 fn visit_map<A>(self, mut map: A) -> ::std::result::Result<Self::Value, A::Error>
488 where
489 A: ::ruststep::serde::de::MapAccess<'de>,
490 {
491 let key: String = map
492 .next_key()?
493 .expect("Empty map cannot be accepted as ruststep Holder");
494 if key != "SUB_1" {
495 use ruststep::serde::de::{Error, Unexpected};
496 return Err(A::Error::invalid_value(Unexpected::Other(&key), &self));
497 }
498 let value = map.next_value()?;
499 Ok(value)
500 }
501 }
502 #[automatically_derived]
503 impl<'de> ::ruststep::serde::de::Deserialize<'de> for Sub1Holder {
504 fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
505 where
506 D: ::ruststep::serde::de::Deserializer<'de>,
507 {
508 deserializer.deserialize_tuple_struct("SUB_1", 2usize, Sub1HolderVisitor {})
509 }
510 }
511 #[automatically_derived]
512 impl ::ruststep::tables::WithVisitor for Sub1Holder {
513 type Visitor = Sub1HolderVisitor;
514 fn visitor_new() -> Self::Visitor {
515 Sub1HolderVisitor {}
516 }
517 }
518 "###);
519 }
520}