dbc_rs/message/
message_builder.rs

1use crate::{
2    error::lang,
3    {Error, Message, Result, Signal, SignalBuilder},
4};
5use std::string::String;
6
7#[derive(Debug)]
8pub struct MessageBuilder {
9    id: Option<u32>,
10    name: Option<String>,
11    dlc: Option<u8>,
12    sender: Option<String>,
13    signals: Vec<SignalBuilder>,
14}
15
16impl MessageBuilder {
17    pub fn new() -> Self {
18        Self {
19            id: None,
20            name: None,
21            dlc: None,
22            sender: None,
23            signals: Vec::new(),
24        }
25    }
26
27    #[must_use]
28    pub fn id(mut self, id: u32) -> Self {
29        self.id = Some(id);
30        self
31    }
32
33    #[must_use]
34    pub fn name(mut self, name: impl AsRef<str>) -> Self {
35        self.name = Some(name.as_ref().to_string());
36        self
37    }
38
39    #[must_use]
40    pub fn dlc(mut self, dlc: u8) -> Self {
41        self.dlc = Some(dlc);
42        self
43    }
44
45    #[must_use]
46    pub fn sender(mut self, sender: impl AsRef<str>) -> Self {
47        self.sender = Some(sender.as_ref().to_string());
48        self
49    }
50
51    #[must_use]
52    pub fn add_signal(mut self, signal: SignalBuilder) -> Self {
53        self.signals.push(signal);
54        self
55    }
56
57    #[must_use]
58    pub fn add_signals(mut self, signals: impl IntoIterator<Item = SignalBuilder>) -> Self {
59        self.signals.extend(signals);
60        self
61    }
62
63    #[must_use]
64    pub fn signals(mut self, signals: Vec<SignalBuilder>) -> Self {
65        self.signals = signals;
66        self
67    }
68
69    #[must_use]
70    pub fn clear_signals(mut self) -> Self {
71        self.signals.clear();
72        self
73    }
74
75    fn extract_fields(self) -> Result<(u32, String, u8, String, Vec<SignalBuilder>)> {
76        let id = self.id.ok_or(Error::Message(lang::MESSAGE_ID_REQUIRED))?;
77        let name = self.name.ok_or(Error::Message(lang::MESSAGE_NAME_EMPTY))?;
78        let dlc = self.dlc.ok_or(Error::Message(lang::MESSAGE_DLC_REQUIRED))?;
79        let sender = self.sender.ok_or(Error::Message(lang::MESSAGE_SENDER_EMPTY))?;
80        Ok((id, name, dlc, sender, self.signals))
81    }
82
83    #[must_use = "validation result should be checked"]
84    pub fn validate(mut self) -> Result<Self> {
85        // Extract fields (this consumes signals, but we'll reconstruct)
86        let signals_clone = self.signals.clone();
87        let id = self.id.ok_or(Error::Message(lang::MESSAGE_ID_REQUIRED))?;
88        let name = self.name.ok_or(Error::Message(lang::MESSAGE_NAME_EMPTY))?;
89        let dlc = self.dlc.ok_or(Error::Message(lang::MESSAGE_DLC_REQUIRED))?;
90        let sender = self.sender.ok_or(Error::Message(lang::MESSAGE_SENDER_EMPTY))?;
91        // Build signals for validation using cloned signals
92        let built_signals: Vec<Signal> = signals_clone
93            .into_iter()
94            .map(|sig_builder| sig_builder.build())
95            .collect::<Result<Vec<_>>>()?;
96        // Validate signals directly
97        Message::validate_internal(id, &name, dlc, &sender, &built_signals)?;
98        // Reconstruct from original data (signals were cloned before, so use original)
99        self.id = Some(id);
100        self.name = Some(name);
101        self.dlc = Some(dlc);
102        self.sender = Some(sender);
103        // signals are already set (we cloned before, so self.signals is still there)
104        Ok(self)
105    }
106}
107
108impl Default for MessageBuilder {
109    fn default() -> Self {
110        Self::new()
111    }
112}
113
114impl MessageBuilder {
115    pub fn build(self) -> Result<Message> {
116        let (id, name, dlc, sender, signals) = self.extract_fields()?;
117        // Build all signals first
118        let built_signals: Vec<Signal> = signals
119            .into_iter()
120            .map(|sig_builder| sig_builder.build())
121            .collect::<Result<Vec<_>>>()?;
122        // Validate before construction
123        Message::validate_internal(id, &name, dlc, &sender, &built_signals)?;
124        // Convert name and sender to String<{ MAX_NAME_SIZE }>
125
126        Ok(Message::new(
127            id,
128            name.into(),
129            dlc,
130            sender.into(),
131            built_signals,
132        ))
133    }
134}