dbc_rs/
macros.rs

1//! Macros for reducing builder boilerplate.
2//!
3//! This module provides macros that generate common builder patterns,
4//! reducing code duplication and ensuring consistency across all builders.
5
6/// Generates a scalar field setter method.
7///
8/// Creates a setter method that takes ownership of `self`, sets a field to `Some(value)`,
9/// and returns `self` for method chaining.
10///
11/// # Arguments
12///
13/// * `$field` - The field name
14/// * `$type` - The field type
15/// * `$doc` - Documentation string for the setter
16///
17/// # Examples
18///
19/// ```ignore
20/// impl MessageBuilder {
21///     builder_setter!(id, u32, "Sets the CAN message ID");
22/// }
23///
24/// // Expands to:
25/// // /// Sets the CAN message ID
26/// // #[must_use = "builder method returns modified builder"]
27/// // pub fn id(mut self, id: u32) -> Self {
28/// //     self.id = Some(id);
29/// //     self
30/// // }
31/// ```
32#[macro_export]
33macro_rules! builder_setter {
34    ($field:ident, $type:ty, $doc:expr) => {
35        #[doc = $doc]
36        #[must_use = "builder method returns modified builder"]
37        pub fn $field(mut self, $field: $type) -> Self {
38            self.$field = Some($field);
39            self
40        }
41    };
42}
43
44/// Generates a string field setter method.
45///
46/// Creates a setter method that accepts `impl AsRef<str>`, converts it to `String`,
47/// wraps it in `Some`, and returns `self` for method chaining.
48///
49/// # Arguments
50///
51/// * `$field` - The field name
52/// * `$doc` - Documentation string for the setter
53///
54/// # Examples
55///
56/// ```ignore
57/// impl MessageBuilder {
58///     builder_string_setter!(name, "Sets the message name");
59/// }
60///
61/// // Expands to:
62/// // /// Sets the message name
63/// // #[must_use = "builder method returns modified builder"]
64/// // pub fn name(mut self, name: impl AsRef<str>) -> Self {
65/// //     self.name = Some(name.as_ref().to_string());
66/// //     self
67/// // }
68/// ```
69#[macro_export]
70macro_rules! builder_string_setter {
71    ($field:ident, $doc:expr) => {
72        #[doc = $doc]
73        #[must_use = "builder method returns modified builder"]
74        pub fn $field(mut self, $field: impl AsRef<str>) -> Self {
75            self.$field = Some($field.as_ref().to_string());
76            self
77        }
78    };
79}
80
81/// Extracts and validates a required `Option<T>` field.
82///
83/// This macro simplifies the common pattern of extracting a required field from an `Option`,
84/// returning an error if the field is `None`.
85///
86/// # Arguments
87///
88/// * `$field` - The `Option<T>` field to extract
89/// * `$error` - The error to return if the field is `None`
90///
91/// # Examples
92///
93/// ```ignore
94/// fn extract_fields(self) -> Result<(u32, String)> {
95///     let id = required_field!(self.id, Error::message(Error::MESSAGE_ID_REQUIRED))?;
96///     let name = required_field!(self.name, Error::message(Error::MESSAGE_NAME_EMPTY))?;
97///     Ok((id, name))
98/// }
99/// ```
100#[macro_export]
101macro_rules! required_field {
102    ($field:expr, $error:expr) => {
103        $field.ok_or_else(|| $error)
104    };
105}