dbn_macros/
lib.rs

1use proc_macro::TokenStream;
2
3mod dbn_attr;
4mod debug;
5mod has_rtype;
6mod py_field_desc;
7mod py_repr;
8mod serialize;
9mod utils;
10
11/// Dummy derive macro to get around `cfg_attr` incompatibility of several
12/// of pyo3's attribute macros. See <https://github.com/PyO3/pyo3/issues/780>.
13///
14/// `MockPyo3` is an invented trait.
15#[proc_macro_derive(MockPyo3, attributes(pyo3))]
16pub fn derive_mock_pyo3(_item: TokenStream) -> TokenStream {
17    TokenStream::new()
18}
19
20/// Dummy derive macro to enable the `dbn` helper attribute for record types
21/// using the `dbn_record` proc macro but neither `CsvSerialize` nor `JsonSerialize` as
22/// helper attributes aren't supported for proc macros alone. See
23/// <https://github.com/rust-lang/rust/issues/65823>.
24#[proc_macro_derive(DbnAttr, attributes(dbn))]
25pub fn dbn_attr(_item: TokenStream) -> TokenStream {
26    TokenStream::new()
27}
28
29/// Derive macro for CSV serialization. Supports the following `dbn` attributes:
30/// - `c_char`: serializes the field as a `char`
31/// - `encode_order`: overrides the position of the field in the CSV table
32/// - `fixed_price`: serializes the field as fixed-price, with the output format
33///   depending on `PRETTY_PX`
34/// - `skip`: does not serialize the field
35/// - `unix_nanos`: serializes the field as a UNIX timestamp, with the output format
36///   depending on `PRETTY_TS`
37///
38/// Note: fields beginning with `_` will automatically be skipped, e.g. `_reserved`
39/// isn't serialized.
40#[proc_macro_derive(CsvSerialize, attributes(dbn))]
41pub fn derive_csv_serialize(input: TokenStream) -> TokenStream {
42    serialize::derive_csv_macro_impl(input)
43}
44
45/// Derive macro for JSON serialization.
46///
47/// Supports the following `dbn` attributes:
48/// - `c_char`: serializes the field as a `char`
49/// - `fixed_price`: serializes the field as fixed-price, with the output format
50///   depending on `PRETTY_PX`
51/// - `skip`: does not serialize the field
52/// - `unix_nanos`: serializes the field as a UNIX timestamp, with the output format
53///   depending on `PRETTY_TS`
54///
55/// Note: fields beginning with `_` will automatically be skipped, e.g. `_reserved`
56/// isn't serialized.
57#[proc_macro_derive(JsonSerialize, attributes(dbn))]
58pub fn derive_json_serialize(input: TokenStream) -> TokenStream {
59    serialize::derive_json_macro_impl(input)
60}
61
62/// Derive macro for field descriptions exposed to Python.
63///
64/// Supports the following `dbn` attributes:
65/// - `c_char`: indicates the field dtype should be a single-character string rather
66///   than an integer
67/// - `encode_order`: overrides the position of the field in the ordered list
68/// - `fixed_price`: indicates this is a fixed-precision field
69/// - `skip`: indicates this field should be hidden
70/// - `unix_nanos`: indicates this is a UNIX nanosecond timestamp field
71#[proc_macro_derive(PyFieldDesc, attributes(dbn))]
72pub fn derive_py_field_desc(input: TokenStream) -> TokenStream {
73    py_field_desc::derive_impl(input)
74}
75
76/// Attribute macro that acts like a derive macro for `Debug` (with customization),
77/// `Record`, `RecordMut`, `HasRType`, `PartialOrd`, and `AsRef<[u8]>`.
78///
79/// Expects 1 or more paths to `u8` constants that are the RTypes associated
80/// with this record.
81///
82/// Supports the following `dbn` attributes:
83/// - `c_char`: format the type as a `char` instead of as a numeric
84/// - `fixed_price`: format the integer as a fixed-precision decimal
85/// - `fmt_binary`: format as a binary
86/// - `fmt_method`: try to format by calling the getter method with the same name as the
87/// - `index_ts`: indicates this field is the primary timestamp for the record
88///   field. If the getter returns an error, the raw field value will be used
89/// - `skip`: won't be included in the `Debug` output
90///
91/// Note: attribute macros don't support helper attributes on their own. If not deriving
92/// `CsvSerialize` or `JsonSerialize`, derive `DbnAttr` to use the `dbn` helper attribute
93/// without a compiler error.
94#[proc_macro_attribute]
95pub fn dbn_record(attr: TokenStream, input: TokenStream) -> TokenStream {
96    has_rtype::attribute_macro_impl(attr, input)
97}
98
99/// Derive macro for Debug representations with the same extensions for DBN records
100/// as `dbn_record`.
101///
102/// Supports the following `dbn` attributes:
103/// - `c_char`: format the type as a `char` instead of as a numeric
104/// - `fixed_price`: format the integer as a fixed-precision decimal
105/// - `fmt_binary`: format as a binary
106/// - `fmt_method`: try to format by calling the getter method with the same name as the
107///   field. If the getter returns an error, the raw field value will be used
108/// - `skip`: won't be included in the `Debug` output
109///
110/// Note: fields beginning with `_` will automatically be skipped, e.g. `_reserved`
111/// isn't included in the `Debug` output.
112#[proc_macro_derive(RecordDebug, attributes(dbn))]
113pub fn derive_record_debug(input: TokenStream) -> TokenStream {
114    debug::derive_impl(input)
115}
116
117/// Derive macro for Python-specific `__repr__` output.
118///
119/// Generates an implementation of `WritePyRepr` for the type.
120/// Uses the `dbn` attributes.
121#[proc_macro_derive(WritePyRepr, attributes(dbn))]
122pub fn derive_write_py_repr(input: TokenStream) -> TokenStream {
123    py_repr::derive_impl(input)
124}
125
126#[cfg(test)]
127mod tests {
128    #[test]
129    fn ui() {
130        let t = trybuild::TestCases::new();
131        t.compile_fail("tests/ui/*.rs");
132    }
133}