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//! ## Dependencies
29//!
30//! When using this macro, your project must include the following dependencies:
31//!
32//! ```toml
33//! [dependencies]
34//! spider-lib = "1.1.1"
35//! serde = { version = "1.0", features = ["derive"] }
36//! serde_json = "1.0"
37//! ```
38//!
39//! ## Example
40//!
41//! ```rust,ignore
42//! use spider_lib::prelude::*;
43//!
44//! #[scraped_item]
45//! struct Article {
46//! title: String,
47//! content: String,
48//! author: String,
49//! published_date: String,
50//! }
51//!
52//! // The macro generates all necessary implementations automatically
53//! // including serialization, deserialization, and the ScrapedItem trait
54//! //
55//! // Note: Make sure your Cargo.toml includes serde and serde_json as dependencies
56//! ```
57
58extern crate proc_macro;
59
60use proc_macro::TokenStream;
61use quote::quote;
62use syn::{parse_macro_input, ItemStruct};
63
64/// A procedural macro to derive the `ScrapedItem` trait.
65///
66/// This macro:
67/// 1. Implements the ScrapedItem trait
68/// 2. Adds serde Serialize and Deserialize derives
69/// 3. Makes use of items that should be in scope via prelude import
70///
71/// # Dependencies
72///
73/// Your project must include `serde` and `serde_json` as direct dependencies:
74///
75/// ```toml
76/// [dependencies]
77/// serde = { version = "1.0", features = ["derive"] }
78/// serde_json = "1.0"
79/// ```
80#[proc_macro_attribute]
81pub fn scraped_item(_attr: TokenStream, item: TokenStream) -> TokenStream {
82 let ast = parse_macro_input!(item as ItemStruct);
83 let name = &ast.ident;
84
85 let expanded = quote! {
86 #[derive(
87 ::serde::Serialize,
88 ::serde::Deserialize,
89 Clone,
90 Debug
91 )]
92 #ast
93
94 impl ScrapedItem for #name {
95 fn as_any(&self) -> &dyn ::std::any::Any {
96 self
97 }
98
99 fn box_clone(&self) -> Box<dyn ScrapedItem + Send + Sync> {
100 Box::new(self.clone())
101 }
102
103 fn to_json_value(&self) -> ::serde_json::Value {
104 ::serde_json::to_value(self).unwrap()
105 }
106 }
107 };
108
109 TokenStream::from(expanded)
110}
111