pinenut_derive/
lib.rs

1//! The internal derive crate for `Pinenut`. Implements the following derive
2//! macros: `pinenut_derive::Builder`, `pinenut_derive::Encode`,
3//! `pinenut_derive::Decode`.
4
5use proc_macro::TokenStream;
6use syn::{parse_macro_input, DeriveInput};
7
8use crate::{
9    builder::impl_builder,
10    codec::{impl_decode, impl_encode},
11};
12
13mod builder;
14mod codec;
15mod misc;
16
17/// `Derive Macro` to automatically implement the `Builder Pattern` for structs that
18/// already implement the `Default` and `Clone` traits.
19///
20/// # Examples
21///
22/// Use it as follows:
23///
24/// ```
25/// use pinenut_derive::Builder;
26///
27/// #[derive(Builder, Default, Clone)]
28/// pub struct MyStruct<T> {
29///     field_one: i32,
30///     field_two: String,
31///     field_three: T,
32/// }
33/// ```
34///
35/// Will generate code looks like this:
36///
37/// ```
38/// # #[derive(Default, Clone)]
39/// # pub struct MyStruct<T> {
40/// #     field_one: i32,
41/// #     field_two: String,
42/// #     field_three: T,
43/// # }
44/// pub struct MyStructBuilder<T: Default + Clone>(MyStruct<T>);
45///
46/// impl<T: Default + Clone> MyStruct<T> {
47///     pub fn builder() -> MyStructBuilder<T> {
48///         MyStructBuilder::new()
49///     }
50/// }
51///
52/// impl<T: Default + Clone> MyStructBuilder<T> {
53///     pub fn new() -> Self {
54///         Self(Default::default())
55///     }
56///
57///     pub fn build(&self) -> MyStruct<T> {
58///         Clone::clone(&self.0)
59///     }
60///
61///     pub fn field_one(&mut self, field_one: i32) -> &mut Self {
62///         self.0.field_one = field_one;
63///         self
64///     }
65///
66///     pub fn field_two(&mut self, field_two: String) -> &mut Self {
67///         self.0.field_two = field_two;
68///         self
69///     }
70///
71///     pub fn field_three(&mut self, field_three: T) -> &mut Self {
72///         self.0.field_three = field_three;
73///         self
74///     }
75/// }
76/// ```
77#[proc_macro_derive(Builder)]
78pub fn derive_builder(input: TokenStream) -> TokenStream {
79    let input = parse_macro_input!(input as DeriveInput);
80    impl_builder(input).into()
81}
82
83/// `Derive Macro` to automatically implement the `Encode` trait for structs.
84///
85/// # Examples
86///
87/// Use it as follows:
88///
89/// ```ignore
90/// use pinenut_derive::Encode;
91///
92/// #[derive(Encode)]
93/// struct MyStruct<'a, T> {
94///     field_one: T,
95///     field_two: &'a str,
96/// }
97/// ```
98///
99/// Will generate code looks like this:
100///
101/// ```ignore
102/// impl<'a, T: codec::Encode> codec::Encode for MyStruct<'a, T> {
103///     fn encode<S>(&self, sink: &mut S) -> Result<(), S::Error>
104///         where
105///             S: codec::Sink,
106///     {
107///         codec::Encode::encode(&self.field_one, sink)?;
108///         codec::Encode::encode(&self.field_two, sink)?;
109///         Ok(())
110///     }
111/// }
112/// ```
113#[proc_macro_derive(Encode)]
114pub fn derive_encode(input: TokenStream) -> TokenStream {
115    let input = parse_macro_input!(input as DeriveInput);
116    impl_encode(input).into()
117}
118
119/// `Derive Macro` to automatically implement the `Decode` trait for structs.
120///
121/// # Examples
122///
123/// Use it as follows:
124///
125/// ```ignore
126/// use pinenut_derive::Encode;
127///
128/// #[derive(Decode)]
129/// struct MyStruct<'a, T> {
130///     field_one: T,
131///     field_two: &'a str,
132/// }
133/// ```
134///
135/// Will generate code looks like this:
136///
137/// ```ignore
138/// impl<'de: 'a, 'a, T: codec::Decode<'de>> codec::Decode<'de> for MyStruct<'a, T> {
139///     fn decode<S>(source: &mut S) -> Result<Self, S::Error>
140///         where
141///             S: codec::Source<'de>,
142///     {
143///         Ok(MyStruct {
144///             field_one: codec::Decode::decode(source)?,
145///             field_two: codec::Decode::decode(source)?,
146///         })
147///     }
148/// }
149/// ```
150#[proc_macro_derive(Decode)]
151pub fn derive_decode(input: TokenStream) -> TokenStream {
152    let input = parse_macro_input!(input as DeriveInput);
153    impl_decode(input).into()
154}