dbc_rs/message/
message_builder.rs1use crate::{
2 error::{Error, Result, messages},
3 message::Message,
4 signal::Signal,
5};
6
7#[cfg(feature = "alloc")]
8#[derive(Debug, Clone, Default)]
9pub struct MessageBuilder {
10 id: Option<u32>,
11 name: Option<String>,
12 dlc: Option<u8>,
13 sender: Option<String>,
14 signals: Vec<Signal<'static>>,
15}
16
17#[cfg(feature = "alloc")]
18impl MessageBuilder {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 #[must_use]
24 pub fn id(mut self, id: u32) -> Self {
25 self.id = Some(id);
26 self
27 }
28
29 #[must_use]
30 pub fn name(mut self, name: impl AsRef<str>) -> Self {
31 self.name = Some(name.as_ref().to_string());
32 self
33 }
34
35 #[must_use]
36 pub fn dlc(mut self, dlc: u8) -> Self {
37 self.dlc = Some(dlc);
38 self
39 }
40
41 #[must_use]
42 pub fn sender(mut self, sender: impl AsRef<str>) -> Self {
43 self.sender = Some(sender.as_ref().to_string());
44 self
45 }
46
47 #[must_use]
48 pub fn add_signal(mut self, signal: Signal<'static>) -> Self {
49 self.signals.push(signal);
50 self
51 }
52
53 #[must_use]
54 pub fn add_signals(mut self, signals: impl IntoIterator<Item = Signal<'static>>) -> Self {
55 self.signals.extend(signals);
56 self
57 }
58
59 #[must_use]
60 pub fn signals(mut self, signals: Vec<Signal<'static>>) -> Self {
61 self.signals = signals;
62 self
63 }
64
65 #[must_use]
66 pub fn clear_signals(mut self) -> Self {
67 self.signals.clear();
68 self
69 }
70
71 fn extract_fields(self) -> Result<(u32, String, u8, String, Vec<Signal<'static>>)> {
72 let id = self
73 .id
74 .ok_or_else(|| Error::Message(messages::MESSAGE_ID_REQUIRED.to_string()))?;
75 let name = self
76 .name
77 .ok_or_else(|| Error::Message(messages::MESSAGE_NAME_EMPTY.to_string()))?;
78 let dlc = self
79 .dlc
80 .ok_or_else(|| Error::Message(messages::MESSAGE_DLC_REQUIRED.to_string()))?;
81 let sender = self
82 .sender
83 .ok_or_else(|| Error::Message(messages::MESSAGE_SENDER_EMPTY.to_string()))?;
84 Ok((id, name, dlc, sender, self.signals))
85 }
86
87 #[must_use = "validation result should be checked"]
88 pub fn validate(self) -> Result<Self> {
89 let (id, name, dlc, sender, signals) = self.extract_fields()?;
90 let signals_options: Vec<Option<Signal<'static>>> =
92 signals.iter().cloned().map(Some).collect();
93 let signals_options_slice: &[Option<Signal<'static>>] = &signals_options;
94 Message::validate_internal(
95 id,
96 &name,
97 dlc,
98 &sender,
99 signals_options_slice,
100 signals_options_slice.len(),
101 crate::ParseOptions::new(), )
103 .map_err(Error::from)?;
104 Ok(Self {
105 id: Some(id),
106 name: Some(name),
107 dlc: Some(dlc),
108 sender: Some(sender),
109 signals,
110 })
111 }
112
113 pub fn build(self) -> Result<Message<'static>> {
114 let (id, name, dlc, sender, signals) = self.extract_fields()?;
115 let signals_options: Vec<Option<Signal<'static>>> =
117 signals.iter().cloned().map(Some).collect();
118 let signals_options_slice: &[Option<Signal<'static>>] = &signals_options;
119 Message::validate_internal(
121 id,
122 &name,
123 dlc,
124 &sender,
125 signals_options_slice,
126 signals_options_slice.len(),
127 crate::ParseOptions::new(), )
129 .map_err(|e| match e {
130 crate::error::ParseError::Version(msg) => Error::Dbc(String::from(msg)),
131 _ => Error::ParseError(e),
132 })?;
133 let name_boxed: Box<str> = name.into_boxed_str();
135 let name_static: &'static str = Box::leak(name_boxed);
136 let sender_boxed: Box<str> = sender.into_boxed_str();
137 let sender_static: &'static str = Box::leak(sender_boxed);
138 let signals_boxed: Box<[Signal<'static>]> = signals.into_boxed_slice();
140 let signals_static: &'static [Signal<'static>] = Box::leak(signals_boxed);
141 Ok(Message::new(
142 id,
143 name_static,
144 dlc,
145 sender_static,
146 signals_static,
147 ))
148 }
149}