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//! ## 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::{ItemStruct, parse_macro_input};
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}