dbc_rs/value_descriptions/builder/
mod.rs

1use crate::{Error, MAX_VALUE_DESCRIPTIONS, Result, ValueDescriptions, error::check_max_limit};
2
3/// Builder for creating `ValueDescriptions` programmatically.
4///
5/// This builder allows you to construct value descriptions when building DBC files
6/// programmatically. It validates that entries are within limits.
7///
8/// # Examples
9///
10/// ```rust,no_run
11/// use dbc_rs::ValueDescriptionsBuilder;
12///
13/// let value_descriptions = ValueDescriptionsBuilder::new()
14///     .add_entry(0, "Park")
15///     .add_entry(1, "Reverse")
16///     .add_entry(2, "Neutral")
17///     .add_entry(3, "Drive")
18///     .build()?;
19///
20/// assert_eq!(value_descriptions.get(0), Some("Park"));
21/// assert_eq!(value_descriptions.get(1), Some("Reverse"));
22/// # Ok::<(), dbc_rs::Error>(())
23/// ```
24///
25/// # Validation
26///
27/// The builder validates:
28/// - Maximum of 64 value descriptions (MAX_VALUE_DESCRIPTIONS)
29///
30/// # Feature Requirements
31///
32/// This builder requires the `std` feature to be enabled.
33#[derive(Debug)]
34pub struct ValueDescriptionsBuilder {
35    entries: Vec<(u64, String)>,
36}
37
38impl ValueDescriptionsBuilder {
39    /// Creates a new `ValueDescriptionsBuilder` with an empty entry list.
40    ///
41    /// # Examples
42    ///
43    /// ```rust,no_run
44    /// use dbc_rs::ValueDescriptionsBuilder;
45    ///
46    /// let builder = ValueDescriptionsBuilder::new();
47    /// let value_descriptions = builder.build()?;
48    /// assert!(value_descriptions.is_empty());
49    /// # Ok::<(), dbc_rs::Error>(())
50    /// ```
51    pub fn new() -> Self {
52        Self {
53            entries: Vec::new(),
54        }
55    }
56
57    /// Adds a value-description pair to the builder.
58    ///
59    /// # Arguments
60    ///
61    /// * `value` - The numeric value (u64)
62    /// * `description` - The human-readable description
63    ///
64    /// # Examples
65    ///
66    /// ```rust,no_run
67    /// use dbc_rs::ValueDescriptionsBuilder;
68    ///
69    /// let builder = ValueDescriptionsBuilder::new()
70    ///     .add_entry(0, "Off")
71    ///     .add_entry(1, "On");
72    /// # Ok::<(), dbc_rs::Error>(())
73    /// ```
74    #[must_use = "builder method returns modified builder"]
75    pub fn add_entry(mut self, value: u64, description: impl AsRef<str>) -> Self {
76        if self.entries.len() < MAX_VALUE_DESCRIPTIONS {
77            self.entries.push((value, description.as_ref().to_string()));
78        }
79        self
80    }
81
82    /// Builds the `ValueDescriptions` from the builder.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the number of entries exceeds the maximum allowed.
87    ///
88    /// # Examples
89    ///
90    /// ```rust,no_run
91    /// use dbc_rs::ValueDescriptionsBuilder;
92    ///
93    /// let value_descriptions = ValueDescriptionsBuilder::new()
94    ///     .add_entry(0, "Park")
95    ///     .add_entry(1, "Drive")
96    ///     .build()?;
97    /// # Ok::<(), dbc_rs::Error>(())
98    /// ```
99    pub fn build(self) -> Result<ValueDescriptions> {
100        if let Some(err) = check_max_limit(
101            self.entries.len(),
102            MAX_VALUE_DESCRIPTIONS,
103            Error::Decoding(Error::VALUE_DESCRIPTIONS_TOO_MANY),
104        ) {
105            return Err(err);
106        }
107
108        // Use Cow::Owned for owned strings (no leak needed)
109        let cow_entries: Vec<(u64, String)> = self.entries.into_iter().collect();
110
111        Ok(ValueDescriptions::from_slice(&cow_entries))
112    }
113}
114
115impl Default for ValueDescriptionsBuilder {
116    fn default() -> Self {
117        Self::new()
118    }
119}