1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Quork procedural macros crate

#![warn(clippy::pedantic)]
#![warn(missing_docs)]

use proc_macro_error::proc_macro_error;
use syn::{parse_macro_input, DeriveInput, LitStr};

mod const_str;
mod enum_list;
mod from_tuple;
mod new;
mod strip;
mod time_fn;

#[macro_use]
extern crate quote;

/// Implement [`quork::ListVariants`] for enums
#[proc_macro_derive(ListVariants)]
#[proc_macro_error]
pub fn derive_enum_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    enum_list::enum_list(&ast).into()
}

/// Implement `const_to_string` for enum variants.
///
/// Converts an enum variant to a string literal, within a constant context.
#[proc_macro_derive(ConstStr)]
pub fn derive_const_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    const_str::derive(&ast).into()
}

/// Implement `new` fn for structs
///
/// Will follow the form of `new(field: Type, ...) -> Self`, where all fields are required.
#[proc_macro_derive(New)]
#[proc_macro_error]
pub fn derive_new(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    new::derive(&ast).into()
}

/// Implement the [`std::convert::From`] trait for converting tuples into tuple structs
#[proc_macro_derive(FromTuple)]
#[proc_macro_error]
pub fn derive_from_tuple(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    from_tuple::derive(&ast).into()
}

/// Time a given function
///
/// Measures the start and finish times of the function, and prints them at the end of the function.
///
/// You can pass "s", "ms", "ns"
#[proc_macro_attribute]
#[proc_macro_error]
pub fn time(
    args: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let args_str = args.to_string();
    let fmt = match args_str.as_str() {
        "ms" | "milliseconds" => time_fn::TimeFormat::Milliseconds,
        "ns" | "nanoseconds" => time_fn::TimeFormat::Nanoseconds,
        _ => time_fn::TimeFormat::Seconds,
    };
    time_fn::attribute(fmt, &input.into()).into()
}

/// Strip whitespace from the right of a string literal on each line
#[proc_macro]
pub fn strip_lines(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let literal = parse_macro_input!(input as LitStr);

    strip::funclike(&literal, &strip::Alignment::None).into()
}

/// Strip whitespace from the left and right of a string literal on each line
#[proc_macro]
pub fn rstrip_lines(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let literal = parse_macro_input!(input as LitStr);

    strip::funclike(&literal, &strip::Alignment::Right).into()
}

/// Strip whitespace from the left of a string literal on each line
#[proc_macro]
pub fn lstrip_lines(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let literal = parse_macro_input!(input as LitStr);

    strip::funclike(&literal, &strip::Alignment::Left).into()
}