simple_someip/protocol/sd/
entry.rs1use crate::{
2 protocol::{
3 Error,
4 byte_order::{ReadBytesExt, WriteBytesExt},
5 },
6 traits::WireFormat,
7};
8
9pub const ENTRY_SIZE: usize = 16;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12enum EntryType {
13 FindService,
14 OfferService,
15 StopOfferService,
16 Subscribe,
17 SubscribeAck,
18}
19
20impl TryFrom<u8> for EntryType {
21 type Error = Error;
22 fn try_from(value: u8) -> Result<Self, Error> {
23 match value {
24 0x00 => Ok(EntryType::FindService),
25 0x01 => Ok(EntryType::OfferService),
26 0x02 => Ok(EntryType::StopOfferService),
27 0x06 => Ok(EntryType::Subscribe),
28 0x07 => Ok(EntryType::SubscribeAck),
29 _ => Err(Error::InvalidSDEntryType(value)),
30 }
31 }
32}
33
34impl From<EntryType> for u8 {
35 fn from(service_entry_type: EntryType) -> u8 {
36 match service_entry_type {
37 EntryType::FindService => 0x00,
38 EntryType::OfferService => 0x01,
39 EntryType::StopOfferService => 0x02,
40 EntryType::Subscribe => 0x06,
41 EntryType::SubscribeAck => 0x07,
42 }
43 }
44}
45
46#[derive(Clone, Copy, Debug, Eq, PartialEq)]
47pub struct OptionsCount {
48 pub first_options_count: u8,
49 pub second_options_count: u8,
50}
51
52impl From<u8> for OptionsCount {
53 fn from(value: u8) -> Self {
54 let first_options_count = (value & 0xf0) >> 4;
55 let second_options_count = value & 0x0f;
56
57 Self {
58 first_options_count,
59 second_options_count,
60 }
61 }
62}
63
64impl From<OptionsCount> for u8 {
65 fn from(options_count: OptionsCount) -> u8 {
66 ((options_count.first_options_count << 4) & 0xf0)
67 | (options_count.second_options_count & 0x0f)
68 }
69}
70
71impl OptionsCount {
72 #[must_use]
73 pub fn new(first_options_count: u8, second_options_count: u8) -> Self {
74 assert!(first_options_count < 16);
75 assert!(second_options_count < 16);
76 OptionsCount {
77 first_options_count,
78 second_options_count,
79 }
80 }
81}
82
83#[derive(Clone, Debug, Eq, PartialEq)]
84pub struct EventGroupEntry {
85 pub index_first_options_run: u8,
86 pub index_second_options_run: u8,
87 pub options_count: OptionsCount,
88 pub service_id: u16,
89 pub instance_id: u16,
90 pub major_version: u8,
91 pub ttl: u32,
93 pub counter: u16,
94 pub event_group_id: u16,
95}
96
97impl EventGroupEntry {
98 #[must_use]
99 pub fn new(
100 service_id: u16,
101 instance_id: u16,
102 major_version: u8,
103 ttl: u32,
104 event_group_id: u16,
105 ) -> Self {
106 Self {
107 index_first_options_run: 0,
108 index_second_options_run: 0,
109 options_count: OptionsCount::new(1, 0),
110 service_id,
111 instance_id,
112 major_version,
113 ttl,
114 counter: 0,
115 event_group_id,
116 }
117 }
118}
119
120impl WireFormat for EventGroupEntry {
121 fn decode<T: embedded_io::Read>(reader: &mut T) -> Result<Self, crate::protocol::Error> {
122 let index_first_options_run = reader.read_u8()?;
123 let index_second_options_run = reader.read_u8()?;
124 let options_count = OptionsCount::from(reader.read_u8()?);
125 let service_id = reader.read_u16_be()?;
126 let instance_id = reader.read_u16_be()?;
127 let major_version = reader.read_u8()?;
128 let ttl = reader.read_u24_be()?;
129 let counter = reader.read_u16_be()? & 0x000f;
130 let event_group_id = reader.read_u16_be()?;
131 Ok(Self {
132 index_first_options_run,
133 index_second_options_run,
134 options_count,
135 service_id,
136 instance_id,
137 major_version,
138 ttl,
139 counter,
140 event_group_id,
141 })
142 }
143
144 fn required_size(&self) -> usize {
145 16
146 }
147
148 fn encode<T: embedded_io::Write>(
149 &self,
150 writer: &mut T,
151 ) -> Result<usize, crate::protocol::Error> {
152 writer.write_u8(self.index_first_options_run)?;
153 writer.write_u8(self.index_second_options_run)?;
154 writer.write_u8(u8::from(self.options_count))?;
155 writer.write_u16_be(self.service_id)?;
156 writer.write_u16_be(self.instance_id)?;
157 writer.write_u8(self.major_version)?;
158 writer.write_u24_be(self.ttl)?;
159 writer.write_u16_be(self.counter)?;
160 writer.write_u16_be(self.event_group_id)?;
161 Ok(16)
162 }
163}
164
165#[derive(Clone, Debug, Eq, PartialEq)]
166pub struct ServiceEntry {
167 pub index_first_options_run: u8,
168 pub index_second_options_run: u8,
169 pub options_count: OptionsCount,
170 pub service_id: u16,
171 pub instance_id: u16,
172 pub major_version: u8,
173 pub ttl: u32,
175 pub minor_version: u32,
176}
177
178impl ServiceEntry {
179 #[must_use]
180 pub fn find(service_id: u16) -> Self {
181 Self {
182 index_first_options_run: 0,
183 index_second_options_run: 0,
184 options_count: OptionsCount::new(1, 0),
185 service_id,
186 instance_id: 0xFFFF,
187 major_version: 0xFF,
188 ttl: 0x00FF_FFFF,
189 minor_version: 0xFFFF_FFFF,
190 }
191 }
192}
193
194impl WireFormat for ServiceEntry {
195 fn decode<R: embedded_io::Read>(reader: &mut R) -> Result<Self, Error> {
196 let index_first_options_run = reader.read_u8()?;
197 let index_second_options_run = reader.read_u8()?;
198 let options_count = OptionsCount::from(reader.read_u8()?);
199 let service_id = reader.read_u16_be()?;
200 let instance_id = reader.read_u16_be()?;
201 let major_version = reader.read_u8()?;
202 let ttl = reader.read_u24_be()?;
203 let minor_version = reader.read_u32_be()?;
204 Ok(Self {
205 index_first_options_run,
206 index_second_options_run,
207 options_count,
208 service_id,
209 instance_id,
210 major_version,
211 ttl,
212 minor_version,
213 })
214 }
215
216 fn required_size(&self) -> usize {
217 16
218 }
219
220 fn encode<W: embedded_io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
221 writer.write_u8(self.index_first_options_run)?;
222 writer.write_u8(self.index_second_options_run)?;
223 writer.write_u8(u8::from(self.options_count))?;
224 writer.write_u16_be(self.service_id)?;
225 writer.write_u16_be(self.instance_id)?;
226 writer.write_u8(self.major_version)?;
227 writer.write_u24_be(self.ttl)?;
228 writer.write_u32_be(self.minor_version)?;
229 Ok(16)
230 }
231}
232
233#[derive(Clone, Debug, Eq, PartialEq)]
234pub enum Entry {
235 FindService(ServiceEntry),
236 OfferService(ServiceEntry),
237 StopOfferService(ServiceEntry),
238 SubscribeEventGroup(EventGroupEntry),
239 SubscribeAckEventGroup(EventGroupEntry),
240}
241
242impl Entry {
243 #[must_use]
244 pub fn first_options_count(&self) -> u8 {
245 match self {
246 Entry::FindService(service_entry)
247 | Entry::OfferService(service_entry)
248 | Entry::StopOfferService(service_entry) => {
249 service_entry.options_count.first_options_count
250 }
251 Entry::SubscribeEventGroup(event_group_entry)
252 | Entry::SubscribeAckEventGroup(event_group_entry) => {
253 event_group_entry.options_count.first_options_count
254 }
255 }
256 }
257
258 #[must_use]
259 pub fn second_options_count(&self) -> u8 {
260 match self {
261 Entry::FindService(service_entry)
262 | Entry::OfferService(service_entry)
263 | Entry::StopOfferService(service_entry) => {
264 service_entry.options_count.second_options_count
265 }
266 Entry::SubscribeEventGroup(event_group_entry)
267 | Entry::SubscribeAckEventGroup(event_group_entry) => {
268 event_group_entry.options_count.second_options_count
269 }
270 }
271 }
272
273 #[must_use]
274 pub fn total_options_count(&self) -> u8 {
275 self.first_options_count() + self.second_options_count()
276 }
277}
278
279impl WireFormat for Entry {
280 fn decode<R: embedded_io::Read>(reader: &mut R) -> Result<Self, Error> {
281 let entry_type = EntryType::try_from(reader.read_u8()?)?;
282 match entry_type {
283 EntryType::FindService => {
284 let service_entry = ServiceEntry::decode(reader)?;
285 Ok(Entry::FindService(service_entry))
286 }
287 EntryType::OfferService => {
288 let service_entry = ServiceEntry::decode(reader)?;
289 Ok(Entry::OfferService(service_entry))
290 }
291 EntryType::StopOfferService => {
292 let service_entry = ServiceEntry::decode(reader)?;
293 Ok(Entry::StopOfferService(service_entry))
294 }
295 EntryType::Subscribe => {
296 let event_group_entry = EventGroupEntry::decode(reader)?;
297 Ok(Entry::SubscribeEventGroup(event_group_entry))
298 }
299 EntryType::SubscribeAck => {
300 let event_group_entry = EventGroupEntry::decode(reader)?;
301 Ok(Entry::SubscribeAckEventGroup(event_group_entry))
302 }
303 }
304 }
305
306 fn required_size(&self) -> usize {
307 1 + match self {
308 Entry::FindService(service_entry)
309 | Entry::OfferService(service_entry)
310 | Entry::StopOfferService(service_entry) => service_entry.required_size(),
311 Entry::SubscribeEventGroup(event_group_entry)
312 | Entry::SubscribeAckEventGroup(event_group_entry) => event_group_entry.required_size(),
313 }
314 }
315
316 fn encode<W: embedded_io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
317 match self {
318 Entry::FindService(service_entry) => {
319 writer.write_u8(u8::from(EntryType::FindService))?;
320 service_entry.encode(writer)
321 }
322 Entry::OfferService(service_entry) => {
323 writer.write_u8(u8::from(EntryType::OfferService))?;
324 service_entry.encode(writer)
325 }
326 Entry::StopOfferService(service_entry) => {
327 writer.write_u8(u8::from(EntryType::StopOfferService))?;
328 service_entry.encode(writer)
329 }
330 Entry::SubscribeEventGroup(event_group_entry) => {
331 writer.write_u8(u8::from(EntryType::Subscribe))?;
332 event_group_entry.encode(writer)
333 }
334 Entry::SubscribeAckEventGroup(event_group_entry) => {
335 writer.write_u8(u8::from(EntryType::SubscribeAck))?;
336 event_group_entry.encode(writer)
337 }
338 }
339 }
340}