Skip to main content

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