sparkles_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{LitStr, parse_macro_input, Expr};
4use syn::parse::{Parse, ParseStream};
5use syn::token::Comma;
6
7/// Create instant event with given name
8/// # Example
9/// ```rust
10/// sparkles_macro::instant_event!("Packet received");
11/// ```
12#[proc_macro]
13pub fn instant_event(input: TokenStream) -> TokenStream {
14    let input = parse_macro_input!(input as LitStr);
15    let s = input.value();
16    let hash = calculate_hash(&s);
17
18    let expanded = quote! {
19        sparkles::instant_event(#hash, #s)
20    };
21
22    TokenStream::from(expanded)
23}
24
25/// Create range event with given name
26/// 
27/// Can be finished with two options:
28/// 1. Drop the guard
29/// 2. Call `sparkles_macro::range_event_end!(guard, "name")`
30/// 
31/// # Example
32/// ```rust
33/// let packet_proc = sparkles_macro::range_event_start!("Packet parsing");
34/// // Do some work
35/// let Ok(data) = parse_packet(&packet) else {
36///    sparkles_macro::range_event_end!(packet_proc, "Failed");
37/// };
38/// sparkles_macro::range_event_end!(packet_proc, "OK");
39/// ```
40#[proc_macro]
41pub fn range_event_start(input: TokenStream) -> TokenStream {
42    let input = parse_macro_input!(input as LitStr);
43    let s = input.value();
44    let hash = calculate_hash(&s);
45
46    let expanded = quote! {
47        sparkles::range_event_start(#hash, #s)
48    };
49
50    TokenStream::from(expanded)
51}
52
53struct RangeEventStartInput {
54    guard: Expr,
55    _comma: Comma,
56    name: LitStr,
57}
58
59impl Parse for RangeEventStartInput {
60    fn parse(input: ParseStream) -> syn::Result<Self> {
61        Ok(Self {
62            guard: input.parse()?,
63            _comma: input.parse()?,
64            name: input.parse()?,
65        })
66    }
67}
68
69/// Finish range event with given name
70/// If you don't want to assign name to the event end, simply drop the guard.
71///
72/// # Example
73/// ```rust
74/// let packet_proc = sparkles_macro::range_event_start!("Packet parsing");
75/// // Do some work
76/// let Ok(data) = parse_packet(&packet) else {
77///    sparkles_macro::range_event_end!(packet_proc, "Failed");
78/// };
79/// sparkles_macro::range_event_end!(packet_proc, "OK");
80/// ```
81#[proc_macro]
82pub fn range_event_end(input: TokenStream) -> TokenStream {
83    let RangeEventStartInput{guard, name, ..} = parse_macro_input!(input as RangeEventStartInput);
84    let s = name.value();
85    let hash = calculate_hash(&s);
86
87    let expanded = quote! {
88        #guard.end(#hash, #s)
89    };
90
91    TokenStream::from(expanded)
92}
93
94fn calculate_hash(s: &str) -> u32 {
95    use std::collections::hash_map::DefaultHasher;
96    use std::hash::{Hash, Hasher};
97
98    let mut hasher = DefaultHasher::new();
99    s.hash(&mut hasher);
100    hasher.finish() as u32
101}
102
103#[proc_macro]
104pub fn calc_hash(input: TokenStream) -> TokenStream {
105    let input = parse_macro_input!(input as LitStr);
106    let s = input.value();
107    let hash = calculate_hash(&s);
108
109    let expanded = quote! {
110        #hash
111    };
112
113    TokenStream::from(expanded)
114}