spider_macro/lib.rs
1//! # spider-macro
2//!
3//! Provides procedural macros for the `spider-lib` framework to reduce boilerplate code.
4//!
5//! ## Overview
6//!
7//! The `spider-macro` crate contains procedural macros that automate the
8//! implementation of common traits and patterns used in the spider framework.
9//! These macros significantly reduce the amount of boilerplate code required
10//! when defining custom data structures for scraped items.
11//!
12//! ## Key Macros
13//!
14//! - **`#[scraped_item]`**: Derives the `ScrapedItem` trait along with necessary
15//! implementations for serialization, deserialization, cloning, and type
16//! conversions. This macro automatically implements all required traits for
17//! a struct to be used as a scraped item in the framework.
18//!
19//! ## Features
20//!
21//! - **Automatic Trait Derivation**: Implements `Serialize`, `Deserialize`,
22//! `Clone`, and `Debug` traits automatically
23//! - **ScrapedItem Implementation**: Provides the complete implementation of
24//! the `ScrapedItem` trait required by the framework
25//! - **Type Safety**: Maintains type safety while reducing boilerplate
26//! - **Performance**: Generates efficient code without runtime overhead
27//!
28//! ## Example
29//!
30//! ```rust,ignore
31//! use spider_macro::scraped_item;
32//!
33//! #[scraped_item]
34//! struct Article {
35//! title: String,
36//! content: String,
37//! author: String,
38//! published_date: String,
39//! }
40//!
41//! // The macro generates all necessary implementations automatically
42//! // including serialization, deserialization, and the ScrapedItem trait
43//! ```
44
45extern crate proc_macro;
46
47use proc_macro::TokenStream;
48use quote::quote;
49use syn::{parse_macro_input, ItemStruct};
50
51/// A procedural macro to derive the `ScrapedItem` trait.
52#[proc_macro_attribute]
53pub fn scraped_item(_attr: TokenStream, item: TokenStream) -> TokenStream {
54 let ast = parse_macro_input!(item as ItemStruct);
55 let name = &ast.ident;
56
57 let expanded = quote! {
58 #[derive(::spider_util::serde::Serialize, ::spider_util::serde::Deserialize, Clone, Debug)]
59 #ast
60
61 impl ::spider_util::item::ScrapedItem for #name {
62 fn as_any(&self) -> &dyn ::std::any::Any {
63 self
64 }
65
66 fn box_clone(&self) -> Box<dyn ::spider_util::item::ScrapedItem + Send + Sync> {
67 Box::new(self.clone())
68 }
69
70 fn to_json_value(&self) -> ::spider_util::serde_json::Value {
71 ::spider_util::serde_json::to_value(self).unwrap()
72 }
73 }
74 };
75
76 TokenStream::from(expanded)
77}
78