serde_json_helpers/lib.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0+
2
3//! A collection of procedural macros compatible with stable Rust 2018 that simplify
4//! some common operations not covered by `serde_derive`.
5//!
6//! Whilst this crate is named `serde_json_helpers`, `serde_json` is not a requirement
7//! to use it; it's just what the proc macros were intended to be helpful for.
8//!
9//! # Examples
10//!
11//! ## `serde_enum_string`
12//!
13//! ```
14//! use serde_json_helpers::serde_enum_string;
15//!
16//! #[serde_enum_string(transform = "snake_case")]
17//! #[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
18//! enum ExampleEnum {
19//! Option1,
20//! Option2,
21//! Option3,
22//! AnotherOption,
23//! }
24//!
25//! fn main() {
26//! let out1 =
27//! serde_json::to_string(&ExampleEnum::Option1).expect("Unable to serialize ExampleEnum");
28//! let out2 =
29//! serde_json::to_string(&ExampleEnum::Option2).expect("Unable to serialize ExampleEnum");
30//! let out3 =
31//! serde_json::to_string(&ExampleEnum::Option3).expect("Unable to serialize ExampleEnum");
32//! let out4 = serde_json::to_string(&ExampleEnum::AnotherOption)
33//! .expect("Unable to serialize ExampleEnum");
34//!
35//! println!("Serialized ExampleEnum::Option1: {}", out1);
36//! println!("Serialized ExampleEnum::Option2: {}", out2);
37//! println!("Serialized ExampleEnum::Option3: {}", out3);
38//! println!("Serialized ExampleEnum::AnotherOption: {}", out4);
39//!
40//! let in1 = serde_json::from_str::<ExampleEnum>(&*out1).expect("Unable to deserialize");
41//! let in2 = serde_json::from_str::<ExampleEnum>(&*out2).expect("Unable to deserialize");
42//! let in3 = serde_json::from_str::<ExampleEnum>(&*out3).expect("Unable to deserialize");
43//! let in4 = serde_json::from_str::<ExampleEnum>(&*out4).expect("Unable to deserialize");
44//!
45//! println!("Deserialized {}: {:?}", out1, in1);
46//! println!("Deserialized {}: {:?}", out2, in2);
47//! println!("Deserialized {}: {:?}", out3, in3);
48//! println!("Deserialized {}: {:?}", out4, in4);
49//!
50//! println!(
51//! "Bad deserialized value {}: {:?}",
52//! "\"bad_value\"",
53//! serde_json::from_str::<ExampleEnum>("\"bad_value\"")
54//! );
55//! }
56//! ```
57
58#![recursion_limit = "128"]
59
60extern crate proc_macro;
61
62use proc_macro::TokenStream;
63
64mod enum_string;
65mod helpers;
66mod string_transform;
67
68/// Allows a C-style `enum` to be serialized as a string, useful for human-readable
69/// JSON.
70///
71/// Takes two optional attributes:
72///
73/// * `transform = "<type>"` - transform the `enum` variants by name into the same
74/// formats as supported by the serde attribute `rename_all`. This includes:
75/// * `lowercase` - makes variant names _lowercase_
76/// * `UPPERCASE` - makes variant names _UPPERCASE_
77/// * `PascalCase` - makes variant names _PascalCase_
78/// * `camelCase` - makes variant names _camelCase_
79/// * `snake_case` - makes variant names _snake\_case_
80/// * `SCREAMING_SNAKE_CASE` - makes variant names _SCREAMING\_SNAKE\_CASE_
81/// * `kebab-case` - makes variant names _kebab-case_
82/// * `SCREAMING-KEBAB-CASE` - makes variant names _SCREAMING-KEBAB-CASE_
83///
84/// If unspecified, the `enum` variant names will be passed through unmodified.
85///
86/// * `prepend_enum_name` - Add the name of the `enum` to the values for each variant. This will
87/// be prepended to the variant name before running the transform described above.
88///
89/// Note that this macro is incompatible with existing `Serialize` and `Deserialize` `impl`s.
90/// If a Serialize or Deserialize derive is detected, this macro will panic, but if you `impl` them
91/// directly you will just get normal compiler issues which you're on your own to figure out.
92#[proc_macro_attribute]
93pub fn serde_enum_string(attr: TokenStream, item: TokenStream) -> TokenStream {
94 enum_string::serde_enum_string_impl(attr, item)
95}