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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! Derive builders for your structs.
//!
//! The derive macro [StructBuilder] creates new structs that can be used to build the struct being derived from that follow the builder pattern.
//! The builder can be used to create the struct from only required fields (those without the [Option] type) and modify the content of the struct.
//!
//! A struct builder enforces required fields to be specified and allows optional arguments to be specified post-construction.
//! This is done by defining a "params" struct that the builder depends on to be initialized. This struct defines all the fields
//! in the original struct that don't have the "Option" type. Once the builder is initialized with the params, both required and optional fields
//! can be updated by calling builder methods (using the identifiers `with_<field>`).
//!
//! # Examples
//!
//! ## Using [StructBuilder] to build a request with named fields.
//! ```
//! use struct_builder::StructBuilder;
//!
//! #[derive(StructBuilder)]
//! pub struct CreateUserRequest {
//! pub email: String,
//! pub first_name: Option<String>,
//! pub last_name: Option<String>,
//! pub age: Option<u64>
//! }
//!
//! let params = CreateUserRequestParams {
//! email: "john.doe@email.com".to_owned()
//! };
//! let request = CreateUserRequest::builder(params)
//! .with_first_name(Some("John".to_owned()))
//! .with_age(Some(35))
//! .build();
//!
//! assert_eq!(request.email, "john.doe@email.com".to_owned());
//! assert_eq!(request.first_name, Some("John".to_owned()));
//! assert_eq!(request.last_name, None);
//! assert_eq!(request.age, Some(35));
//! ```
//!
//! ## Using [StructBuilder] to build a tuple (unnamed) struct.
//! ```
//! use struct_builder::StructBuilder;
//!
//! /// First, Middle, and Last names.
//! #[derive(StructBuilder)]
//! pub struct FullName(pub String, pub Option<String>, pub String);
//!
//! let params = FullNameParams("John".to_owned(), "Doe".to_owned());
//! let request = FullName::builder(params)
//! .with_1(Some("Harold".to_owned()))
//! .build();
//!
//! assert_eq!(request.0, "John".to_owned());
//! assert_eq!(request.1, Some("Harold".to_owned()));
//! assert_eq!(request.2, "Doe".to_owned());
//! ```
//!
//! ## Converting a params struct directly with no builder.
//! ```
//! use struct_builder::StructBuilder;
//!
//! #[derive(StructBuilder)]
//! pub struct CreateUserRequest {
//! pub email: String,
//! pub first_name: Option<String>,
//! pub last_name: Option<String>,
//! }
//!
//! let request = CreateUserRequest::from(CreateUserRequestParams {
//! email: "john.doe@email.com".to_owned()
//! });
//!
//! assert_eq!(request.email, "john.doe@email.com".to_owned());
//! assert_eq!(request.first_name, None);
//! assert_eq!(request.last_name, None);
//! ```
//!
//! ## Creating a builder directly
//! ```
//! use struct_builder::StructBuilder;
//!
//! #[derive(StructBuilder)]
//! pub struct CreateUserRequest {
//! pub email: String,
//! pub first_name: Option<String>,
//! pub last_name: Option<String>,
//! }
//!
//! let request = CreateUserRequest {
//! email: "john.doe@email.com".to_owned(),
//! first_name: Some("John".to_owned()),
//! last_name: None
//! };
//! let rebuilt_request = CreateUserRequestBuilder::from(request)
//! .with_last_name(Some("Doe".to_owned()))
//! .build();
//!
//! assert_eq!(rebuilt_request.email, "john.doe@email.com".to_owned());
//! assert_eq!(rebuilt_request.first_name, Some("John".to_owned()));
//! assert_eq!(rebuilt_request.last_name, Some("Doe".to_owned()));
//! ```
extern crate proc_macro;
mod builder;
use builder::ItemBuilder;
use syn::{parse_macro_input, ItemStruct};
/// Derive a struct builder for a struct.
///
///
#[proc_macro_derive(StructBuilder)]
pub fn derive_builder(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
let item = parse_macro_input!(item as ItemStruct);
let builder = ItemBuilder::from(item);
proc_macro2::TokenStream::from_iter(vec![
builder.new_params_struct(),
builder.new_builder_struct(),
builder.new_item_impl(),
builder.new_builder_impl(),
builder.new_builder_from_item(),
builder.new_item_from_builder(),
builder.new_conversion_impl_from_params()
]).into()
}