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}