doip_definitions/builder/
mod.rs1use crate::header::{PayloadType, ProtocolVersion};
2use crate::payload::AliveCheckRequest;
3use crate::{header::DoipHeader, message::DoipMessage, payload::DoipPayload};
4
5#[derive(Default, Debug)]
10pub struct DoipMessageBuilder {
11 header: DoipHeader,
13
14 payload: DoipPayload,
16}
17
18impl Default for DoipPayload {
19 fn default() -> Self {
21 DoipPayload::AliveCheckRequest(AliveCheckRequest {})
22 }
23}
24
25impl Default for DoipHeader {
26 fn default() -> Self {
32 Self {
33 protocol_version: ProtocolVersion::DefaultValue,
34 inverse_protocol_version: !(ProtocolVersion::DefaultValue as u8),
35 payload_type: PayloadType::AliveCheckRequest,
36 payload_length: Default::default(),
37 }
38 }
39}
40
41impl DoipMessageBuilder {
42 #[must_use]
50 pub fn new() -> Self {
51 DoipMessageBuilder::default()
52 }
53
54 #[must_use]
71 pub fn protocol_version(mut self, protocol_version: impl Into<ProtocolVersion>) -> Self {
72 self.header.protocol_version = protocol_version.into();
73 self.header.inverse_protocol_version = !(self.header.protocol_version as u8);
74 self
75 }
76
77 #[must_use]
103 pub fn payload(mut self, payload: impl Into<DoipPayload>) -> Self {
104 self.payload = payload.into();
105
106 let (payload_type, size) = match self.payload {
107 DoipPayload::GenericNack(ref pay) => (PayloadType::GenericNack, size_of_val(pay)),
108 DoipPayload::VehicleIdentificationRequest(ref pay) => {
109 (PayloadType::VehicleIdentificationRequest, size_of_val(pay))
110 }
111 DoipPayload::VehicleIdentificationRequestEid(ref pay) => (
112 PayloadType::VehicleIdentificationRequestEid,
113 size_of_val(pay),
114 ),
115 DoipPayload::VehicleIdentificationRequestVin(ref pay) => (
116 PayloadType::VehicleIdentificationRequestVin,
117 size_of_val(pay),
118 ),
119 DoipPayload::VehicleAnnouncementMessage(ref pay) => {
120 (PayloadType::VehicleAnnouncementMessage, size_of_val(pay))
121 }
122 DoipPayload::RoutingActivationRequest(ref pay) => {
123 (PayloadType::RoutingActivationRequest, size_of_val(pay))
124 }
125 DoipPayload::RoutingActivationResponse(ref pay) => {
126 (PayloadType::RoutingActivationResponse, size_of_val(pay))
127 }
128 DoipPayload::AliveCheckRequest(ref pay) => {
129 (PayloadType::AliveCheckRequest, size_of_val(pay))
130 }
131 DoipPayload::AliveCheckResponse(ref pay) => {
132 (PayloadType::AliveCheckResponse, size_of_val(pay))
133 }
134 DoipPayload::EntityStatusRequest(ref pay) => {
135 (PayloadType::EntityStatusRequest, size_of_val(pay))
136 }
137 DoipPayload::EntityStatusResponse(ref pay) => {
138 (PayloadType::EntityStatusResponse, size_of_val(pay))
139 }
140 DoipPayload::PowerInformationRequest(ref pay) => {
141 (PayloadType::PowerInformationRequest, size_of_val(pay))
142 }
143 DoipPayload::PowerInformationResponse(ref pay) => {
144 (PayloadType::PowerInformationResponse, size_of_val(pay))
145 }
146 DoipPayload::DiagnosticMessage(ref pay) => (PayloadType::DiagnosticMessage, pay.size()),
147 DoipPayload::DiagnosticMessageAck(ref pay) => {
148 (PayloadType::DiagnosticMessageAck, size_of_val(pay))
149 }
150 DoipPayload::DiagnosticMessageNack(ref pay) => {
151 (PayloadType::DiagnosticMessageNack, size_of_val(pay))
152 }
153 };
154
155 self.header.payload_type = payload_type;
156 self.header.payload_length =
157 u32::try_from(size).expect("This should never be larger than u32.");
158
159 self
160 }
161
162 #[must_use]
180 pub fn build(self) -> DoipMessage {
181 DoipMessage {
182 header: self.header,
183 payload: self.payload,
184 }
185 }
186}
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::{
191 definitions::{DOIP_DIAG_COMMON_SOURCE_LEN, DOIP_DIAG_COMMON_TARGET_LEN},
192 payload::{DiagnosticMessage, DoipPayload},
193 };
194
195 #[test]
196 fn test_diagnostic_message_payload() {
197 let message = vec![0x01, 0x02, 0x03];
198 let message_length = message.len();
199 let payload = DoipPayload::DiagnosticMessage(DiagnosticMessage {
200 source_address: [0x12, 0x34],
201 target_address: [0x56, 0x78],
202 message,
203 });
204 let builder = DoipMessageBuilder::new().payload(payload);
205 let doip_message = builder.build();
206
207 assert_eq!(
208 doip_message.header.payload_type,
209 PayloadType::DiagnosticMessage
210 );
211 assert_eq!(
212 doip_message.header.payload_length,
213 (DOIP_DIAG_COMMON_SOURCE_LEN + DOIP_DIAG_COMMON_TARGET_LEN + message_length) as u32
214 );
215 }
216}