1use crate::err::{SdReadError, SdValueError, SdWriteError};
2use std::io::{Read, Seek, Write};
3
4pub const MIN_SD_HEADER_LENGTH: usize = 1 + 3 + 4 + 4;
7
8pub const EVENT_ENTRY_INITIAL_DATA_REQUESTED_FLAG: u8 = 0b1000_0000;
9
10pub mod sd_flags {
12 pub const REBOOT_FLAG: u8 = 0b1000_0000;
15
16 pub const UNICAST_FLAG: u8 = 0b0100_0000;
25
26 pub const EXPLICIT_INITIAL_DATA_CONTROL_FLAG: u8 = 0b0010_0000;
33}
34
35pub mod sd_entries {
37 use super::{SdEventGroupEntryType, SdServiceEntryType};
38
39 pub const MAX_ENTRIES_LEN: u32 = crate::SOMEIP_MAX_PAYLOAD_LEN_UDP - 4 - 4 - 4;
64
65 pub const ENTRY_LEN: usize = 16;
68
69 #[derive(Clone, Debug, Eq, PartialEq)]
71 pub struct ServiceEntry {
72 pub _type: SdServiceEntryType,
73 pub index_first_option_run: u8,
74 pub index_second_option_run: u8,
75 pub number_of_options_1: u8,
76 pub number_of_options_2: u8,
77 pub service_id: u16,
78 pub instance_id: u16,
79 pub major_version: u8,
80 pub ttl: u32,
81 pub minor_version: u32,
82 }
83
84 #[derive(Clone, Debug, Eq, PartialEq)]
86 pub struct EventgroupEntry {
87 pub _type: SdEventGroupEntryType,
88 pub index_first_option_run: u8,
89 pub index_second_option_run: u8,
90 pub number_of_options_1: u8,
91 pub number_of_options_2: u8,
92 pub service_id: u16,
93 pub instance_id: u16,
94 pub major_version: u8,
95 pub ttl: u32,
96 pub initial_data_requested: bool,
98 pub counter: u8,
101 pub eventgroup_id: u16,
102 }
103}
104
105pub mod sd_options {
107 use super::TransportProtocol;
108
109 pub const MAX_OPTIONS_LEN: u32 = crate::SOMEIP_MAX_PAYLOAD_LEN_UDP - 4 - 4 - 4;
134
135 pub const DISCARDABLE_FLAG: u8 = 0b1000_0000;
138
139 pub const CONFIGURATION_TYPE: u8 = 0x01;
141
142 pub const LOAD_BALANCING_LEN: u16 = 0x0005;
144
145 pub const LOAD_BALANCING_TYPE: u8 = 0x02;
147
148 pub const IPV4_ENDPOINT_LEN: u16 = 0x0009;
150
151 pub const IPV4_ENDPOINT_TYPE: u8 = 0x04;
153
154 pub const IPV6_ENDPOINT_LEN: u16 = 0x0015;
156
157 pub const IPV6_ENDPOINT_TYPE: u8 = 0x06;
159
160 pub const IPV4_MULTICAST_LEN: u16 = 0x0009;
162
163 pub const IPV4_MULTICAST_TYPE: u8 = 0x14;
165
166 pub const IPV6_MULTICAST_LEN: u16 = 0x0015;
168
169 pub const IPV6_MULTICAST_TYPE: u8 = 0x16;
171
172 pub const IPV4_SD_ENDPOINT_LEN: u16 = 0x009;
174
175 pub const IPV4_SD_ENDPOINT_TYPE: u8 = 0x24;
177
178 pub const IPV6_SD_ENDPOINT_LEN: u16 = 0x0015;
180
181 pub const IPV6_SD_ENDPOINT_TYPE: u8 = 0x26;
183
184 #[derive(Clone, Debug, Eq, PartialEq)]
185 pub struct ConfigurationOption {
186 pub discardable: bool,
188 pub configuration_string: Vec<u8>,
190 }
191
192 #[derive(Clone, Debug, Eq, PartialEq)]
193 pub struct LoadBalancingOption {
194 pub discardable: bool,
196 pub priority: u16,
197 pub weight: u16,
198 }
199
200 #[derive(Clone, Debug, Eq, PartialEq)]
201 pub struct Ipv4EndpointOption {
202 pub ipv4_address: [u8; 4],
203 pub transport_protocol: TransportProtocol,
204 pub port: u16,
205 }
206
207 #[derive(Clone, Debug, Eq, PartialEq)]
208 pub struct Ipv6EndpointOption {
209 pub ipv6_address: [u8; 16],
210 pub transport_protocol: TransportProtocol,
211 pub port: u16,
212 }
213
214 #[derive(Clone, Debug, Eq, PartialEq)]
215 pub struct Ipv4MulticastOption {
216 pub ipv4_address: [u8; 4],
217 pub transport_protocol: TransportProtocol,
218 pub port: u16,
219 }
220
221 #[derive(Clone, Debug, Eq, PartialEq)]
222 pub struct Ipv6MulticastOption {
223 pub ipv6_address: [u8; 16],
224 pub transport_protocol: TransportProtocol,
225 pub port: u16,
226 }
227
228 #[derive(Clone, Debug, Eq, PartialEq)]
229 pub struct Ipv4SdEndpointOption {
230 pub ipv4_address: [u8; 4],
231 pub transport_protocol: TransportProtocol,
232 pub port: u16,
233 }
234
235 #[derive(Clone, Debug, Eq, PartialEq)]
236 pub struct Ipv6SdEndpointOption {
237 pub ipv6_address: [u8; 16],
238 pub transport_protocol: TransportProtocol,
239 pub port: u16,
240 }
241
242 #[derive(Clone, Debug, Eq, PartialEq)]
250 pub struct UnknownDiscardableOption {
251 pub length: u16,
252 pub option_type: u8,
253 }
254}
255
256use self::sd_entries::*;
257use self::sd_options::*;
258
259#[derive(Clone, Debug, Eq, PartialEq)]
261pub struct SdHeaderFlags {
262 pub reboot: bool,
263 pub unicast: bool,
264 pub explicit_initial_data_control: bool,
265}
266
267impl Default for SdHeaderFlags {
268 fn default() -> Self {
269 SdHeaderFlags {
270 reboot: false,
271 unicast: true,
275 explicit_initial_data_control: true,
276 }
277 }
278}
279
280impl SdHeaderFlags {
281 pub fn to_bytes(&self) -> [u8; 4] {
283 use sd_flags::*;
284 [
285 if self.reboot { REBOOT_FLAG } else { 0 }
286 | if self.unicast { UNICAST_FLAG } else { 0 }
287 | if self.explicit_initial_data_control {
288 EXPLICIT_INITIAL_DATA_CONTROL_FLAG
289 } else {
290 0
291 },
292 0,
293 0,
294 0,
295 ]
296 }
297}
298
299#[derive(Clone, Debug, Default, Eq, PartialEq)]
301pub struct SdHeader {
302 pub flags: SdHeaderFlags,
303 pub entries: Vec<SdEntry>,
307 pub options: Vec<SdOption>,
310}
311
312impl SdHeader {
313 #[inline]
314 pub fn new(reboot: bool, entries: Vec<SdEntry>, options: Vec<SdOption>) -> Self {
315 Self {
316 flags: SdHeaderFlags {
317 reboot,
318 unicast: true,
319 explicit_initial_data_control: true,
320 },
321 entries,
322 options,
323 }
324 }
325
326 #[inline]
327 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
328 pub fn read<T: Read + Seek>(reader: &mut T) -> Result<Self, SdReadError> {
329 SdHeader::read_with_flag(reader, false)
330 }
331
332 #[inline]
333 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
334 pub fn read_with_flag<T: Read + Seek>(
335 reader: &mut T,
336 discard_unknown_option: bool,
337 ) -> Result<Self, SdReadError> {
338 const HEADER_LENGTH: usize = 1 + 3 + 4; let mut header_bytes: [u8; HEADER_LENGTH] = [0; HEADER_LENGTH];
340 reader.read_exact(&mut header_bytes)?;
341
342 let num_entries = {
343 let length_entries = u32::from_be_bytes([
344 header_bytes[4],
345 header_bytes[5],
346 header_bytes[6],
347 header_bytes[7],
348 ]);
349
350 if length_entries > MAX_ENTRIES_LEN {
351 return Err(SdReadError::SdEntriesArrayLengthTooLarge(length_entries));
352 }
353
354 (length_entries as usize) / ENTRY_LEN
358 };
359 let entries = {
360 let mut entries = Vec::new();
361 entries.try_reserve(num_entries)?;
362 for _ in 0..num_entries {
363 entries.push(SdEntry::read(reader)?);
364 }
365 entries
366 };
367
368 let mut options_length = {
369 let mut options_length_bytes: [u8; 4] = [0x00; 4];
370 reader.read_exact(&mut options_length_bytes)?;
371 u32::from_be_bytes(options_length_bytes)
372 };
373
374 if options_length > MAX_OPTIONS_LEN {
375 return Err(SdReadError::SdOptionsArrayLengthTooLarge(options_length));
376 }
377
378 let mut options = Vec::new();
379 options.try_reserve((options_length as usize) / 4)?;
383
384 while options_length > 0 {
385 let (read_bytes, option) = SdOption::read_with_flag(reader, discard_unknown_option)?;
386 options.push(option);
387 options_length -= read_bytes as u32;
388 }
389
390 use sd_flags::*;
392 Ok(Self {
393 flags: SdHeaderFlags {
394 reboot: 0 != header_bytes[0] & REBOOT_FLAG,
395 unicast: 0 != header_bytes[0] & UNICAST_FLAG,
396 explicit_initial_data_control: 0
397 != header_bytes[0] & EXPLICIT_INITIAL_DATA_CONTROL_FLAG,
398 },
399 entries,
400 options,
401 })
402 }
403
404 #[inline]
406 pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), SdWriteError> {
407 writer.write_all(&self.to_bytes_vec()?)?;
408 Ok(())
409 }
410
411 #[inline]
413 pub fn write_to_slice(&self, slice: &mut [u8]) -> Result<(), SdWriteError> {
414 let buffer = self.to_bytes_vec()?;
415 if slice.len() < buffer.len() {
416 use crate::err::SdWriteError::*;
417 Err(UnexpectedEndOfSlice(buffer.len()))
418 } else {
419 for (idx, b) in buffer.iter().enumerate() {
421 slice[idx] = *b;
422 }
423 Ok(())
424 }
425 }
426
427 #[inline]
429 pub fn header_len(&self) -> usize {
430 let options_len: usize = self.options.iter().map(|o| o.header_len()).sum();
432 4 * 3 + self.entries.len() * ENTRY_LEN + options_len
433 }
434
435 #[inline]
437 pub fn to_bytes_vec(&self) -> Result<Vec<u8>, SdValueError> {
438 let entries_len = self.entries.len() * ENTRY_LEN;
440 let options_len: usize = self.options.iter().map(|o| o.header_len()).sum();
441
442 let mut bytes = Vec::with_capacity(4 * 3 + entries_len + options_len);
444
445 bytes.extend_from_slice(&self.flags.to_bytes());
447 bytes.extend_from_slice(&(entries_len as u32).to_be_bytes());
449
450 for e in &self.entries {
452 bytes.extend_from_slice(&e.to_bytes());
453 }
454
455 bytes.extend_from_slice(&(options_len as u32).to_be_bytes());
457 for o in &self.options {
458 o.append_bytes_to_vec(&mut bytes)?;
459 }
460
461 Ok(bytes)
462 }
463}
464
465#[derive(Clone, Debug, Eq, PartialEq)]
466pub enum SdEntry {
467 Service(ServiceEntry),
469
470 Eventgroup(EventgroupEntry),
472}
473
474impl From<ServiceEntry> for SdEntry {
475 #[inline]
476 fn from(e: ServiceEntry) -> Self {
477 SdEntry::Service(e)
478 }
479}
480
481impl From<EventgroupEntry> for SdEntry {
482 #[inline]
483 fn from(o: EventgroupEntry) -> Self {
484 SdEntry::Eventgroup(o)
485 }
486}
487
488impl SdEntry {
489 #[allow(clippy::too_many_arguments)]
490 pub fn new_service_entry(
491 _type: SdServiceEntryType,
492 index_first_option_run: u8,
493 index_second_option_run: u8,
494 number_of_options_1: u8,
495 number_of_options_2: u8,
496 service_id: u16,
497 instance_id: u16,
498 major_version: u8,
499 ttl: u32,
500 minor_version: u32,
501 ) -> Result<Self, SdValueError> {
502 if ttl > 0x00FF_FFFF {
503 Err(SdValueError::TtlTooLarge(ttl))
504 } else if number_of_options_1 > 0x0F {
505 Err(SdValueError::NumberOfOption1TooLarge(number_of_options_1))
506 } else if number_of_options_2 > 0x0F {
507 Err(SdValueError::NumberOfOption2TooLarge(number_of_options_2))
508 } else {
509 Ok(Self::Service(ServiceEntry {
510 _type,
511 index_first_option_run,
512 index_second_option_run,
513 number_of_options_1,
514 number_of_options_2,
515 service_id,
516 instance_id,
517 major_version,
518 ttl,
519 minor_version,
520 }))
521 }
522 }
523
524 #[allow(clippy::too_many_arguments)]
531 pub fn new_find_service_entry(
532 index_first_option_run: u8,
533 index_second_option_run: u8,
534 number_of_options_1: u8,
535 number_of_options_2: u8,
536 service_id: u16,
537 instance_id: u16,
538 major_version: u8,
539 ttl: u32,
540 minor_version: u32,
541 ) -> Result<Self, SdValueError> {
542 if ttl == 0 {
543 Err(SdValueError::TtlZeroIndicatesStopOffering)
544 } else {
545 Self::new_service_entry(
546 SdServiceEntryType::FindService,
547 index_first_option_run,
548 index_second_option_run,
549 number_of_options_1,
550 number_of_options_2,
551 service_id,
552 instance_id,
553 major_version,
554 ttl,
555 minor_version,
556 )
557 }
558 }
559
560 #[allow(clippy::too_many_arguments)]
568 pub fn new_offer_service_entry(
569 index_first_option_run: u8,
570 index_second_option_run: u8,
571 number_of_options_1: u8,
572 number_of_options_2: u8,
573 service_id: u16,
574 instance_id: u16,
575 major_version: u8,
576 ttl: u32,
577 minor_version: u32,
578 ) -> Result<Self, SdValueError> {
579 if ttl == 0 {
580 Err(SdValueError::TtlZeroIndicatesStopOffering)
581 } else {
582 Self::new_service_entry(
583 SdServiceEntryType::OfferService,
584 index_first_option_run,
585 index_second_option_run,
586 number_of_options_1,
587 number_of_options_2,
588 service_id,
589 instance_id,
590 major_version,
591 ttl,
592 minor_version,
593 )
594 }
595 }
596
597 #[allow(clippy::too_many_arguments)]
599 pub fn new_stop_offer_service_entry(
600 index_first_option_run: u8,
601 index_second_option_run: u8,
602 number_of_options_1: u8,
603 number_of_options_2: u8,
604 service_id: u16,
605 instance_id: u16,
606 major_version: u8,
607 minor_version: u32,
608 ) -> Result<Self, SdValueError> {
609 Self::new_service_entry(
610 SdServiceEntryType::OfferService,
611 index_first_option_run,
612 index_second_option_run,
613 number_of_options_1,
614 number_of_options_2,
615 service_id,
616 instance_id,
617 major_version,
618 0x00,
619 minor_version,
620 )
621 }
622
623 #[allow(clippy::too_many_arguments)]
624 pub fn new_eventgroup(
625 _type: SdEventGroupEntryType,
626 index_first_option_run: u8,
627 index_second_option_run: u8,
628 number_of_options_1: u8,
629 number_of_options_2: u8,
630 service_id: u16,
631 instance_id: u16,
632 major_version: u8,
633 ttl: u32,
634 initial_data_requested: bool,
635 counter: u8,
636 eventgroup_id: u16,
637 ) -> Result<Self, SdValueError> {
638 if counter > 0x0F {
639 Err(SdValueError::CounterTooLarge(counter))
640 } else if ttl > 0x00FF_FFFF {
641 Err(SdValueError::TtlTooLarge(ttl))
642 } else if number_of_options_1 > 0x0F {
643 Err(SdValueError::NumberOfOption1TooLarge(number_of_options_1))
644 } else if number_of_options_2 > 0x0F {
645 Err(SdValueError::NumberOfOption2TooLarge(number_of_options_2))
646 } else {
647 Ok(Self::Eventgroup(EventgroupEntry {
648 _type,
649 index_first_option_run,
650 index_second_option_run,
651 number_of_options_1,
652 number_of_options_2,
653 service_id,
654 instance_id,
655 major_version,
656 ttl,
657 initial_data_requested,
658 counter,
659 eventgroup_id,
660 }))
661 }
662 }
663
664 #[inline]
665 pub fn read<T: Read + Seek>(reader: &mut T) -> Result<Self, SdReadError> {
666 let mut entry_bytes: [u8; sd_entries::ENTRY_LEN] = [0; sd_entries::ENTRY_LEN];
667 reader.read_exact(&mut entry_bytes)?;
668
669 let _type_raw = entry_bytes[0];
670 match _type_raw {
671 0x00 => Self::read_service(SdServiceEntryType::FindService, entry_bytes),
672 0x01 => Self::read_service(SdServiceEntryType::OfferService, entry_bytes),
673 0x06 => Self::read_entry_group(SdEventGroupEntryType::Subscribe, entry_bytes),
674 0x07 => Self::read_entry_group(SdEventGroupEntryType::SubscribeAck, entry_bytes),
675 _ => Err(SdReadError::UnknownSdServiceEntryType(_type_raw)),
676 }
677 }
678
679 #[inline]
681 pub fn read_service(
682 _type: SdServiceEntryType,
683 entry_bytes: [u8; sd_entries::ENTRY_LEN],
684 ) -> Result<Self, SdReadError> {
685 Ok(Self::Service(ServiceEntry {
687 _type,
688 index_first_option_run: entry_bytes[1],
689 index_second_option_run: entry_bytes[2],
690 number_of_options_1: entry_bytes[3] >> 4,
691 number_of_options_2: entry_bytes[3] & 0x0F,
692 service_id: u16::from_be_bytes([entry_bytes[4], entry_bytes[5]]),
693 instance_id: u16::from_be_bytes([entry_bytes[6], entry_bytes[7]]),
694 major_version: entry_bytes[8],
695 ttl: u32::from_be_bytes([0x00, entry_bytes[9], entry_bytes[10], entry_bytes[11]]),
696 minor_version: u32::from_be_bytes([
697 entry_bytes[12],
698 entry_bytes[13],
699 entry_bytes[14],
700 entry_bytes[15],
701 ]),
702 }))
703 }
704
705 #[inline]
707 pub fn read_entry_group(
708 _type: SdEventGroupEntryType,
709 entry_bytes: [u8; sd_entries::ENTRY_LEN],
710 ) -> Result<Self, SdReadError> {
711 Ok(Self::Eventgroup(EventgroupEntry {
712 _type,
713 index_first_option_run: entry_bytes[1],
714 index_second_option_run: entry_bytes[2],
715 number_of_options_1: entry_bytes[3] >> 4,
716 number_of_options_2: entry_bytes[3] & 0x0F,
717 service_id: u16::from_be_bytes([entry_bytes[4], entry_bytes[5]]),
718 instance_id: u16::from_be_bytes([entry_bytes[6], entry_bytes[7]]),
719 major_version: entry_bytes[8],
720 ttl: u32::from_be_bytes([0x00, entry_bytes[9], entry_bytes[10], entry_bytes[11]]),
721 initial_data_requested: 0 != entry_bytes[13] & EVENT_ENTRY_INITIAL_DATA_REQUESTED_FLAG,
723 counter: entry_bytes[13] & 0x0F,
725 eventgroup_id: u16::from_be_bytes([entry_bytes[14], entry_bytes[15]]),
726 }))
727 }
728
729 #[inline]
731 pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), SdWriteError> {
732 writer.write_all(&self.to_bytes())?;
733 Ok(())
734 }
735
736 #[inline]
738 pub fn to_bytes(&self) -> [u8; sd_entries::ENTRY_LEN] {
739 match self {
740 SdEntry::Eventgroup(e) => {
741 let mut result = [0x00; sd_entries::ENTRY_LEN];
742
743 result[0] = e._type.clone() as u8;
744 result[1] = e.index_first_option_run;
745 result[2] = e.index_second_option_run;
746 result[3] = (e.number_of_options_1 << 4) | (e.number_of_options_2 & 0x0F);
747
748 let service_id_bytes = e.service_id.to_be_bytes();
749 result[4] = service_id_bytes[0];
750 result[5] = service_id_bytes[1];
751
752 let instance_id_bytes = e.instance_id.to_be_bytes();
753 result[6] = instance_id_bytes[0];
754 result[7] = instance_id_bytes[1];
755
756 result[8] = e.major_version;
757
758 let ttl_bytes = e.ttl.to_be_bytes();
759 result[9] = ttl_bytes[1];
760 result[10] = ttl_bytes[2];
761 result[11] = ttl_bytes[3];
762
763 if e.initial_data_requested {
765 result[13] |= EVENT_ENTRY_INITIAL_DATA_REQUESTED_FLAG;
766 }
767 result[13] |= e.counter & 0x0F;
768
769 let eventgroup_id_bytes = e.eventgroup_id.to_be_bytes();
770 result[14] = eventgroup_id_bytes[0];
771 result[15] = eventgroup_id_bytes[1];
772
773 result
774 }
775 SdEntry::Service(e) => {
776 let mut result = [0x00; sd_entries::ENTRY_LEN];
777
778 result[0] = e._type.clone() as u8;
779 result[1] = e.index_first_option_run;
780 result[2] = e.index_second_option_run;
781 result[3] = (e.number_of_options_1 << 4) | (e.number_of_options_2 & 0x0F);
782
783 let service_id_bytes = e.service_id.to_be_bytes();
784 result[4] = service_id_bytes[0];
785 result[5] = service_id_bytes[1];
786
787 let instance_id_bytes = e.instance_id.to_be_bytes();
788 result[6] = instance_id_bytes[0];
789 result[7] = instance_id_bytes[1];
790
791 result[8] = e.major_version;
792
793 let ttl_bytes = e.ttl.to_be_bytes();
794 result[9] = ttl_bytes[1];
795 result[10] = ttl_bytes[2];
796 result[11] = ttl_bytes[3];
797
798 let minor_version_bytes = e.minor_version.to_be_bytes();
799 result[12] = minor_version_bytes[0];
800 result[13] = minor_version_bytes[1];
801 result[14] = minor_version_bytes[2];
802 result[15] = minor_version_bytes[3];
803
804 result
805 }
806 }
807 }
808
809 pub fn header_len(&self) -> usize {
811 4 * 4
812 }
813}
814
815#[derive(Clone, Debug, Eq, PartialEq)]
816pub enum SdServiceEntryType {
817 FindService = 0x00,
818 OfferService = 0x01,
819}
820
821#[derive(Clone, Debug, Eq, PartialEq)]
822pub enum SdEventGroupEntryType {
823 Subscribe = 0x06,
824 SubscribeAck = 0x07,
825}
826
827#[derive(Clone, Debug, Eq, PartialEq)]
828pub enum SdOptionType {
829 Configuration = 0x01,
830 LoadBalancing = 0x02,
831 Ipv4Endpoint = 0x04,
832 Ipv6Endpoint = 0x06,
833 Ipv4Multicast = 0x14,
834 Ipv6Multicast = 0x16,
835 Ipv4SdEndpoint = 0x24,
836 Ipv6SdEndpoint = 0x26,
837}
838
839#[derive(Copy, Clone, Debug, Eq, PartialEq)]
841pub enum TransportProtocol {
842 Tcp,
843 Udp,
844 Generic(u8),
845}
846
847impl From<TransportProtocol> for u8 {
848 fn from(tp: TransportProtocol) -> u8 {
849 match tp {
850 TransportProtocol::Tcp => 0x06,
851 TransportProtocol::Udp => 0x11,
852 TransportProtocol::Generic(tp) => tp,
853 }
854 }
855}
856
857#[cfg(test)]
858mod test_transport_protocol {
859 use proptest::prelude::*;
860 proptest! {
861 #[test]
862 fn from_u8(argu8 in any::<u8>()) {
863 use super::TransportProtocol::*;
864 assert_eq!(u8::from(Tcp), 0x06);
865 assert_eq!(u8::from(Udp), 0x11);
866 assert_eq!(u8::from(Generic(argu8)), argu8);
867 }
868 }
869}
870
871#[derive(Clone, Debug, Eq, PartialEq)]
872pub enum SdOption {
873 Configuration(ConfigurationOption),
875 LoadBalancing(LoadBalancingOption),
876 Ipv4Endpoint(Ipv4EndpointOption),
877 Ipv6Endpoint(Ipv6EndpointOption),
878 Ipv4Multicast(Ipv4MulticastOption),
879 Ipv6Multicast(Ipv6MulticastOption),
880 Ipv4SdEndpoint(Ipv4SdEndpointOption),
881 Ipv6SdEndpoint(Ipv6SdEndpointOption),
882 UnknownDiscardable(UnknownDiscardableOption),
890}
891
892impl From<ConfigurationOption> for SdOption {
893 #[inline]
894 fn from(o: ConfigurationOption) -> Self {
895 SdOption::Configuration(o)
896 }
897}
898
899impl From<LoadBalancingOption> for SdOption {
900 #[inline]
901 fn from(o: LoadBalancingOption) -> Self {
902 SdOption::LoadBalancing(o)
903 }
904}
905
906impl From<Ipv4EndpointOption> for SdOption {
907 #[inline]
908 fn from(o: Ipv4EndpointOption) -> Self {
909 SdOption::Ipv4Endpoint(o)
910 }
911}
912
913impl From<Ipv6EndpointOption> for SdOption {
914 #[inline]
915 fn from(o: Ipv6EndpointOption) -> Self {
916 SdOption::Ipv6Endpoint(o)
917 }
918}
919
920impl From<Ipv4MulticastOption> for SdOption {
921 #[inline]
922 fn from(o: Ipv4MulticastOption) -> Self {
923 SdOption::Ipv4Multicast(o)
924 }
925}
926
927impl From<Ipv6MulticastOption> for SdOption {
928 #[inline]
929 fn from(o: Ipv6MulticastOption) -> Self {
930 SdOption::Ipv6Multicast(o)
931 }
932}
933
934impl From<Ipv4SdEndpointOption> for SdOption {
935 #[inline]
936 fn from(o: Ipv4SdEndpointOption) -> Self {
937 SdOption::Ipv4SdEndpoint(o)
938 }
939}
940
941impl From<Ipv6SdEndpointOption> for SdOption {
942 #[inline]
943 fn from(o: Ipv6SdEndpointOption) -> Self {
944 SdOption::Ipv6SdEndpoint(o)
945 }
946}
947
948impl From<UnknownDiscardableOption> for SdOption {
949 #[inline]
950 fn from(o: UnknownDiscardableOption) -> Self {
951 SdOption::UnknownDiscardable(o)
952 }
953}
954
955impl SdOption {
956 #[inline]
958 pub fn read<T: Read + Seek>(reader: &mut T) -> Result<(u16, Self), SdReadError> {
959 SdOption::read_with_flag(reader, false)
960 }
961
962 #[inline]
964 pub fn read_with_flag<T: Read + Seek>(
965 reader: &mut T,
966 discard_unknown_option: bool,
967 ) -> Result<(u16, Self), SdReadError> {
968 use self::sd_options::*;
969 use self::SdOption::*;
970 use SdReadError::*;
971
972 let mut option_bytes: [u8; 4] = [0; 4];
973 reader.read_exact(&mut option_bytes)?;
974
975 let length = u16::from_be_bytes([option_bytes[0], option_bytes[1]]);
976 if length < 1 {
977 return Err(SdOptionLengthZero);
978 }
979
980 let type_raw = option_bytes[2];
981 let discardable = 0 != option_bytes[3] & DISCARDABLE_FLAG;
983
984 let expect_len = |expected_len: u16| -> Result<(), SdReadError> {
987 if expected_len == length {
988 Ok(())
989 } else {
990 Err(SdOptionUnexpectedLen {
991 expected_len,
992 actual_len: length,
993 option_type: type_raw,
994 })
995 }
996 };
997
998 let option = match type_raw {
999 CONFIGURATION_TYPE => {
1001 let length_array = (length - 1) as usize;
1002 let mut configuration_string = Vec::with_capacity(length_array);
1003 reader
1004 .take(length_array as u64)
1005 .read_to_end(&mut configuration_string)?;
1006 Configuration(ConfigurationOption {
1007 discardable,
1008 configuration_string,
1009 })
1010 }
1011 LOAD_BALANCING_TYPE => {
1012 expect_len(LOAD_BALANCING_LEN)?;
1013
1014 let mut load_balancing_bytes: [u8; 4] = [0; 4];
1015 reader.read_exact(&mut load_balancing_bytes)?;
1016 LoadBalancing(LoadBalancingOption {
1017 discardable,
1018 priority: u16::from_be_bytes([
1019 load_balancing_bytes[0],
1020 load_balancing_bytes[1],
1021 ]),
1022 weight: u16::from_be_bytes([load_balancing_bytes[2], load_balancing_bytes[3]]),
1023 })
1024 }
1025 IPV4_ENDPOINT_TYPE => {
1026 expect_len(IPV4_ENDPOINT_LEN)?;
1027
1028 let (ipv4_address, transport_protocol, port) = Self::read_ip4_option(reader)?;
1029 Ipv4Endpoint(Ipv4EndpointOption {
1030 ipv4_address,
1031 transport_protocol,
1032 port,
1033 })
1034 }
1035 IPV6_ENDPOINT_TYPE => {
1036 expect_len(IPV6_ENDPOINT_LEN)?;
1037
1038 let (ipv6_address, transport_protocol, port) = Self::read_ip6_option(reader)?;
1039 Ipv6Endpoint(Ipv6EndpointOption {
1040 ipv6_address,
1041 transport_protocol,
1042 port,
1043 })
1044 }
1045 IPV4_MULTICAST_TYPE => {
1046 expect_len(IPV4_MULTICAST_LEN)?;
1047
1048 let (ipv4_address, transport_protocol, port) = Self::read_ip4_option(reader)?;
1049 Ipv4Multicast(Ipv4MulticastOption {
1050 ipv4_address,
1051 transport_protocol,
1052 port,
1053 })
1054 }
1055 IPV6_MULTICAST_TYPE => {
1056 expect_len(IPV6_MULTICAST_LEN)?;
1057
1058 let (ipv6_address, transport_protocol, port) = Self::read_ip6_option(reader)?;
1059 Ipv6Multicast(Ipv6MulticastOption {
1060 ipv6_address,
1061 transport_protocol,
1062 port,
1063 })
1064 }
1065 IPV4_SD_ENDPOINT_TYPE => {
1066 expect_len(IPV4_SD_ENDPOINT_LEN)?;
1067
1068 let (ipv4_address, transport_protocol, port) = Self::read_ip4_option(reader)?;
1069 Ipv4SdEndpoint(Ipv4SdEndpointOption {
1070 ipv4_address,
1071 transport_protocol,
1072 port,
1073 })
1074 }
1075 IPV6_SD_ENDPOINT_TYPE => {
1076 expect_len(IPV6_SD_ENDPOINT_LEN)?;
1077
1078 let (ipv6_address, transport_protocol, port) = Self::read_ip6_option(reader)?;
1079 Ipv6SdEndpoint(Ipv6SdEndpointOption {
1080 ipv6_address,
1081 transport_protocol,
1082 port,
1083 })
1084 }
1085 option_type => {
1086 if discardable || discard_unknown_option {
1087 if length > 1 {
1092 if length > 2 {
1094 reader.seek(std::io::SeekFrom::Current(i64::from(length) - 2))?;
1095 }
1096 let mut buf = [0; 1];
1102 reader.read_exact(&mut buf)?;
1103 }
1104
1105 UnknownDiscardable(UnknownDiscardableOption {
1107 length,
1108 option_type,
1109 })
1110 } else {
1111 return Err(UnknownSdOptionType(option_type));
1112 }
1113 }
1114 };
1115 Ok((3 + length, option))
1116 }
1117
1118 #[inline]
1119 fn read_ip4_option<T: Read>(
1120 reader: &mut T,
1121 ) -> Result<([u8; 4], TransportProtocol, u16), SdReadError> {
1122 let mut ipv4endpoint_bytes: [u8; 8] = [0; 8];
1123 reader.read_exact(&mut ipv4endpoint_bytes)?;
1124
1125 let ipv4_address = [
1127 ipv4endpoint_bytes[0],
1128 ipv4endpoint_bytes[1],
1129 ipv4endpoint_bytes[2],
1130 ipv4endpoint_bytes[3],
1131 ];
1132 let transport_protocol_raw = ipv4endpoint_bytes[5];
1134 let transport_protocol = match transport_protocol_raw {
1135 0x06 => TransportProtocol::Tcp,
1136 0x11 => TransportProtocol::Udp,
1137 other => TransportProtocol::Generic(other),
1138 };
1139
1140 let transport_protocol_number =
1141 u16::from_be_bytes([ipv4endpoint_bytes[6], ipv4endpoint_bytes[7]]);
1142
1143 Ok((ipv4_address, transport_protocol, transport_protocol_number))
1144 }
1145
1146 #[inline]
1147 fn read_ip6_option<T: Read>(
1148 reader: &mut T,
1149 ) -> Result<([u8; 16], TransportProtocol, u16), SdReadError> {
1150 let mut ipv6endpoint_bytes: [u8; 20] = [0; 20];
1151 reader.read_exact(&mut ipv6endpoint_bytes)?;
1152
1153 let ipv6_address = [
1155 ipv6endpoint_bytes[0],
1156 ipv6endpoint_bytes[1],
1157 ipv6endpoint_bytes[2],
1158 ipv6endpoint_bytes[3],
1159 ipv6endpoint_bytes[4],
1160 ipv6endpoint_bytes[5],
1161 ipv6endpoint_bytes[6],
1162 ipv6endpoint_bytes[7],
1163 ipv6endpoint_bytes[8],
1164 ipv6endpoint_bytes[9],
1165 ipv6endpoint_bytes[10],
1166 ipv6endpoint_bytes[11],
1167 ipv6endpoint_bytes[12],
1168 ipv6endpoint_bytes[13],
1169 ipv6endpoint_bytes[14],
1170 ipv6endpoint_bytes[15],
1171 ];
1172 let transport_protocol_raw = ipv6endpoint_bytes[17];
1174 let transport_protocol = match transport_protocol_raw {
1175 0x06 => TransportProtocol::Tcp,
1176 0x11 => TransportProtocol::Udp,
1177 other => TransportProtocol::Generic(other),
1178 };
1179
1180 let transport_protocol_number =
1181 u16::from_be_bytes([ipv6endpoint_bytes[18], ipv6endpoint_bytes[19]]);
1182
1183 Ok((ipv6_address, transport_protocol, transport_protocol_number))
1184 }
1185
1186 #[inline]
1188 pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), SdWriteError> {
1189 use self::sd_options::*;
1190 use self::SdOption::*;
1191
1192 fn write_ipv4<R: Write>(
1193 writer: &mut R,
1194 len: u16,
1195 t: u8,
1196 addr: [u8; 4],
1197 tp: TransportProtocol,
1198 port: u16,
1199 ) -> Result<(), SdWriteError> {
1200 let len_be = len.to_be_bytes();
1201 let port_be = port.to_be_bytes();
1202 writer.write_all(&[
1203 len_be[0],
1204 len_be[1],
1205 t,
1206 0,
1207 addr[0],
1208 addr[1],
1209 addr[2],
1210 addr[3],
1211 0,
1212 tp.into(),
1213 port_be[0],
1214 port_be[1],
1215 ])?;
1216 Ok(())
1217 }
1218
1219 fn write_ipv6<R: Write>(
1220 writer: &mut R,
1221 len: u16,
1222 t: u8,
1223 addr: [u8; 16],
1224 tp: TransportProtocol,
1225 port: u16,
1226 ) -> Result<(), SdWriteError> {
1227 let len_be = len.to_be_bytes();
1228 let port_be = port.to_be_bytes();
1229 writer.write_all(&[
1230 len_be[0],
1231 len_be[1],
1232 t,
1233 0,
1234 addr[0],
1235 addr[1],
1236 addr[2],
1237 addr[3],
1238 addr[4],
1239 addr[5],
1240 addr[6],
1241 addr[7],
1242 addr[8],
1243 addr[9],
1244 addr[10],
1245 addr[11],
1246 addr[12],
1247 addr[13],
1248 addr[14],
1249 addr[15],
1250 0,
1251 tp.into(),
1252 port_be[0],
1253 port_be[1],
1254 ])?;
1255 Ok(())
1256 }
1257
1258 match self {
1259 Configuration(c) => {
1260 let len_be = (1u16 + c.configuration_string.len() as u16).to_be_bytes();
1261 writer.write_all(&[
1262 len_be[0],
1263 len_be[1],
1264 CONFIGURATION_TYPE,
1265 if c.discardable { DISCARDABLE_FLAG } else { 0 },
1266 ])?;
1267 writer.write_all(&c.configuration_string)?;
1268 Ok(())
1269 }
1270 LoadBalancing(o) => {
1271 let len_be = LOAD_BALANCING_LEN.to_be_bytes();
1272 let prio_be = o.priority.to_be_bytes();
1273 let weight_be = o.weight.to_be_bytes();
1274
1275 writer.write_all(&[
1276 len_be[0],
1277 len_be[1],
1278 LOAD_BALANCING_TYPE,
1279 if o.discardable { DISCARDABLE_FLAG } else { 0 },
1280 prio_be[0],
1281 prio_be[1],
1282 weight_be[0],
1283 weight_be[1],
1284 ])?;
1285 Ok(())
1286 }
1287 Ipv4Endpoint(o) => write_ipv4(
1288 writer,
1289 IPV4_ENDPOINT_LEN,
1290 IPV4_ENDPOINT_TYPE,
1291 o.ipv4_address,
1292 o.transport_protocol,
1293 o.port,
1294 ),
1295 Ipv6Endpoint(o) => write_ipv6(
1296 writer,
1297 IPV6_ENDPOINT_LEN,
1298 IPV6_ENDPOINT_TYPE,
1299 o.ipv6_address,
1300 o.transport_protocol,
1301 o.port,
1302 ),
1303 Ipv4Multicast(o) => write_ipv4(
1304 writer,
1305 IPV4_MULTICAST_LEN,
1306 IPV4_MULTICAST_TYPE,
1307 o.ipv4_address,
1308 o.transport_protocol,
1309 o.port,
1310 ),
1311 Ipv6Multicast(o) => write_ipv6(
1312 writer,
1313 IPV6_MULTICAST_LEN,
1314 IPV6_MULTICAST_TYPE,
1315 o.ipv6_address,
1316 o.transport_protocol,
1317 o.port,
1318 ),
1319 Ipv4SdEndpoint(o) => write_ipv4(
1320 writer,
1321 IPV4_SD_ENDPOINT_LEN,
1322 IPV4_SD_ENDPOINT_TYPE,
1323 o.ipv4_address,
1324 o.transport_protocol,
1325 o.port,
1326 ),
1327 Ipv6SdEndpoint(o) => write_ipv6(
1328 writer,
1329 IPV6_SD_ENDPOINT_LEN,
1330 IPV6_SD_ENDPOINT_TYPE,
1331 o.ipv6_address,
1332 o.transport_protocol,
1333 o.port,
1334 ),
1335 UnknownDiscardable(o) => Err(SdWriteError::ValueError(
1336 SdValueError::SdUnknownDiscardableOption(o.option_type),
1337 )),
1338 }
1339 }
1340
1341 pub fn append_bytes_to_vec(&self, buffer: &mut Vec<u8>) -> Result<(), SdValueError> {
1343 use self::sd_options::*;
1344 use self::SdOption::*;
1345
1346 fn append_ip4(
1347 buffer: &mut Vec<u8>,
1348 ipv4_address: [u8; 4],
1349 transport_protocol: TransportProtocol,
1350 port: u16,
1351 ) {
1352 buffer.extend_from_slice(&ipv4_address);
1353 buffer.push(0x00); buffer.push(transport_protocol.into());
1355 buffer.extend_from_slice(&port.to_be_bytes());
1356 }
1357
1358 fn append_ip6(
1359 buffer: &mut Vec<u8>,
1360 ipv6_address: [u8; 16],
1361 transport_protocol: TransportProtocol,
1362 port: u16,
1363 ) {
1364 buffer.extend_from_slice(&ipv6_address);
1365 buffer.push(0x00); buffer.push(transport_protocol.into());
1367 buffer.extend_from_slice(&port.to_be_bytes());
1368 }
1369
1370 match self {
1371 Configuration(o) => {
1372 let length_bytes = (1u16 + o.configuration_string.len() as u16).to_be_bytes();
1374 buffer.extend_from_slice(&length_bytes);
1375 buffer.push(CONFIGURATION_TYPE);
1376 buffer.push(if o.discardable { DISCARDABLE_FLAG } else { 0 });
1377 buffer.extend_from_slice(&o.configuration_string);
1378 }
1379 LoadBalancing(o) => {
1380 buffer.extend_from_slice(&LOAD_BALANCING_LEN.to_be_bytes());
1381 buffer.push(LOAD_BALANCING_TYPE);
1382 buffer.push(if o.discardable { DISCARDABLE_FLAG } else { 0 });
1383 buffer.extend_from_slice(&o.priority.to_be_bytes());
1384 buffer.extend_from_slice(&o.weight.to_be_bytes());
1385 }
1386 Ipv4Endpoint(o) => {
1387 buffer.extend_from_slice(&IPV4_ENDPOINT_LEN.to_be_bytes());
1388 buffer.push(IPV4_ENDPOINT_TYPE);
1389 buffer.push(0x00u8); append_ip4(buffer, o.ipv4_address, o.transport_protocol, o.port);
1391 }
1392 Ipv6Endpoint(o) => {
1393 buffer.extend_from_slice(&IPV6_ENDPOINT_LEN.to_be_bytes());
1394 buffer.push(IPV6_ENDPOINT_TYPE); buffer.push(0x00u8); append_ip6(buffer, o.ipv6_address, o.transport_protocol, o.port);
1397 }
1398 Ipv4Multicast(o) => {
1399 buffer.extend_from_slice(&IPV4_MULTICAST_LEN.to_be_bytes());
1400 buffer.push(IPV4_MULTICAST_TYPE); buffer.push(0x00u8); append_ip4(buffer, o.ipv4_address, o.transport_protocol, o.port);
1403 }
1404 Ipv6Multicast(o) => {
1405 buffer.extend_from_slice(&IPV6_MULTICAST_LEN.to_be_bytes());
1406 buffer.push(IPV6_MULTICAST_TYPE); buffer.push(0x00u8); append_ip6(buffer, o.ipv6_address, o.transport_protocol, o.port);
1409 }
1410 Ipv4SdEndpoint(o) => {
1411 buffer.extend_from_slice(&IPV4_SD_ENDPOINT_LEN.to_be_bytes());
1412 buffer.push(IPV4_SD_ENDPOINT_TYPE);
1413 buffer.push(0x00u8); append_ip4(buffer, o.ipv4_address, o.transport_protocol, o.port);
1415 }
1416 Ipv6SdEndpoint(o) => {
1417 buffer.extend_from_slice(&IPV6_SD_ENDPOINT_LEN.to_be_bytes());
1418 buffer.push(IPV6_SD_ENDPOINT_TYPE); buffer.push(0x00u8); append_ip6(buffer, o.ipv6_address, o.transport_protocol, o.port);
1421 }
1422 UnknownDiscardable(o) => {
1423 return Err(SdValueError::SdUnknownDiscardableOption(o.option_type));
1424 }
1425 }
1426 Ok(())
1427 }
1428
1429 #[inline]
1431 pub fn header_len(&self) -> usize {
1432 use self::sd_options::*;
1433 use self::SdOption::*;
1434
1435 3 + match self {
1436 Configuration(o) => 1 + o.configuration_string.len(),
1437 LoadBalancing(_) => usize::from(LOAD_BALANCING_LEN),
1438 Ipv4Endpoint(_) => usize::from(IPV4_ENDPOINT_LEN),
1439 Ipv6Endpoint(_) => usize::from(IPV6_ENDPOINT_LEN),
1440 Ipv4Multicast(_) => usize::from(IPV4_MULTICAST_LEN),
1441 Ipv6Multicast(_) => usize::from(IPV6_MULTICAST_LEN),
1442 Ipv4SdEndpoint(_) => usize::from(IPV4_SD_ENDPOINT_LEN),
1443 Ipv6SdEndpoint(_) => usize::from(IPV6_SD_ENDPOINT_LEN),
1444 UnknownDiscardable(o) => usize::from(o.length),
1445 }
1446 }
1447}
1448
1449#[cfg(test)]
1450mod tests_sd_header {
1451
1452 use super::*;
1453 use crate::proptest_generators::*;
1454 use assert_matches::*;
1455 use proptest::prelude::*;
1456 use std::io::Cursor;
1457
1458 proptest! {
1459 #[test]
1460 fn write_read(header in sd_header_any()) {
1461
1462 {
1464 let mut buffer: [u8; 10000] = [0; 10000];
1466 header.write_to_slice(&mut buffer).unwrap();
1467
1468 let mut cursor = Cursor::new(&buffer);
1470 let result = SdHeader::read(&mut cursor).unwrap();
1471 assert_eq!(header, result);
1472 }
1473 }
1474 }
1475
1476 #[test]
1477 fn read() {
1478 for len in [sd_entries::MAX_ENTRIES_LEN + 1, u32::MAX] {
1480 let len_be = len.to_be_bytes();
1481 let buffer = [
1482 0, 0, 0, 0, len_be[0], len_be[1], len_be[2], len_be[3], 0, 0, 0, 0,
1484 ];
1485 let mut cursor = Cursor::new(&buffer);
1486 assert_matches!(
1487 SdHeader::read(&mut cursor),
1488 Err(SdReadError::SdEntriesArrayLengthTooLarge(_))
1489 );
1490 }
1491
1492 for len in [sd_options::MAX_OPTIONS_LEN + 1, u32::MAX] {
1494 let len_be = len.to_be_bytes();
1495 let buffer = [
1496 0, 0, 0, 0, 0, 0, 0, 0, len_be[0], len_be[1], len_be[2], len_be[3], 0, 0, 0, 0,
1499 ];
1500 let mut cursor = Cursor::new(&buffer);
1501 assert_matches!(
1502 SdHeader::read(&mut cursor),
1503 Err(SdReadError::SdOptionsArrayLengthTooLarge(_))
1504 );
1505 }
1506 }
1507}
1508
1509#[cfg(test)]
1510mod tests_sd_entry {
1511
1512 use super::*;
1513 use crate::proptest_generators::*;
1514 use proptest::prelude::*;
1515 use std::io::Cursor;
1516
1517 proptest! {
1518 #[test]
1519 fn write_read(service_entry in someip_sd_entry_any()) {
1520
1521 let mut buffer = Vec::new();
1523 service_entry.write(&mut buffer).unwrap();
1524
1525 let mut cursor = Cursor::new(&buffer);
1527 let result = SdEntry::read(&mut cursor).unwrap();
1528 assert_eq!(service_entry, result);
1529 }
1530 }
1531}
1532
1533#[cfg(test)]
1534mod tests_sd_option {
1535
1536 use super::*;
1537 use crate::proptest_generators::*;
1538 use assert_matches::*;
1539 use proptest::prelude::*;
1540 use std::io::Cursor;
1541
1542 proptest! {
1543 #[test]
1544 fn write_read(option in someip_sd_option_any()) {
1545
1546 let mut buffer = Vec::with_capacity(option.header_len());
1548 option.write(&mut buffer).unwrap();
1549
1550 let mut cursor = Cursor::new(&buffer);
1552 let (read_len, result) = SdOption::read(&mut cursor).unwrap();
1553 assert_eq!(buffer.len() as u16, read_len);
1554 assert_eq!(option, result);
1555 }
1556 }
1557
1558 #[test]
1559 fn read() {
1560 use sd_options::*;
1561 {
1563 let buffer = [0x00, 0x00, IPV4_ENDPOINT_TYPE, 0x00];
1564 let mut cursor = std::io::Cursor::new(buffer);
1565 let result = SdOption::read(&mut cursor);
1566 assert_matches!(result, Err(SdReadError::SdOptionLengthZero));
1567 }
1568 for t in [
1570 IPV4_ENDPOINT_TYPE,
1571 IPV4_MULTICAST_TYPE,
1572 IPV4_SD_ENDPOINT_TYPE,
1573 ] {
1574 let buffer = [0x00, 0x01, t, 0x00];
1575 let mut cursor = std::io::Cursor::new(buffer);
1576 let result = SdOption::read(&mut cursor);
1577 assert_matches!(
1578 result,
1579 Err(SdReadError::SdOptionUnexpectedLen {
1580 expected_len: 0x9,
1581 actual_len: 0x1,
1582 option_type: _,
1583 })
1584 );
1585 }
1586 for t in [
1588 IPV6_ENDPOINT_TYPE,
1589 IPV6_MULTICAST_TYPE,
1590 IPV6_SD_ENDPOINT_TYPE,
1591 ] {
1592 let buffer = [0x00, 0x01, t, 0x00];
1593 let mut cursor = std::io::Cursor::new(buffer);
1594 let result = SdOption::read(&mut cursor);
1595 assert_matches!(
1596 result,
1597 Err(SdReadError::SdOptionUnexpectedLen {
1598 expected_len: 0x15,
1599 actual_len: 0x1,
1600 option_type: _,
1601 })
1602 );
1603 }
1604 {
1606 let buffer = [0x00, 0x01, 0xff, 0x00];
1607 let mut cursor = std::io::Cursor::new(buffer);
1608 let result = SdOption::read(&mut cursor);
1609 assert_matches!(result, Err(SdReadError::UnknownSdOptionType(0xFF)));
1610 }
1611 {
1613 let buffer = [0x00, 0x01, 0xff, 0x00];
1614 let mut cursor = std::io::Cursor::new(buffer);
1615 let (len, header) = SdOption::read_with_flag(&mut cursor, true).unwrap();
1616 assert_eq!(
1617 header,
1618 UnknownDiscardableOption {
1619 length: 1,
1620 option_type: 0xff,
1621 }
1622 .into()
1623 );
1624 assert_eq!(4, len);
1625 }
1626 {
1628 let buffer = [0x00, 0x01, 0xff, 0b1000_0000];
1629 let mut cursor = std::io::Cursor::new(buffer);
1630 let (len, header) = SdOption::read(&mut cursor).unwrap();
1631 assert_eq!(
1632 header,
1633 UnknownDiscardableOption {
1634 length: 1,
1635 option_type: 0xff,
1636 }
1637 .into()
1638 );
1639 assert_eq!(4, len);
1640 }
1641 }
1642}
1643
1644#[test]
1645fn sd_header_write_unexpected_end_of_slice() {
1646 use assert_matches::*;
1647
1648 let header = SdHeader::default();
1649 let result = header.write_to_slice(&mut []);
1650 assert_matches!(result, Err(SdWriteError::UnexpectedEndOfSlice(_)));
1651}
1652
1653#[test]
1654fn service_entry_read_unknown_service_entry_type() {
1655 use assert_matches::*;
1656
1657 let mut buffer = [0x00; sd_entries::ENTRY_LEN];
1658 buffer[0] = 0xFF; let mut cursor = std::io::Cursor::new(buffer);
1660 let result = SdEntry::read(&mut cursor);
1661 assert_matches!(result, Err(SdReadError::UnknownSdServiceEntryType(0xFF)));
1662}
1663
1664#[test]
1665fn new_service_entry_ttl_too_large() {
1666 use assert_matches::*;
1667
1668 let result = SdEntry::new_service_entry(
1669 SdServiceEntryType::OfferService,
1670 0,
1671 0,
1672 0,
1673 0,
1674 0,
1675 0,
1676 0,
1677 0xFFFF_FFFF,
1678 0,
1679 );
1680 assert_matches!(result, Err(SdValueError::TtlTooLarge(0xFFFF_FFFF)));
1681}
1682
1683#[test]
1684fn new_service_entry_number_option1_too_large() {
1685 use assert_matches::*;
1686
1687 let result = SdEntry::new_service_entry(
1688 SdServiceEntryType::OfferService,
1689 0,
1690 0,
1691 0xFF,
1692 0,
1693 0,
1694 0,
1695 0,
1696 0,
1697 0,
1698 );
1699 assert_matches!(result, Err(SdValueError::NumberOfOption1TooLarge(0xFF)));
1700}
1701
1702#[test]
1703fn new_service_entry_number_option2_too_large() {
1704 use assert_matches::*;
1705
1706 let result = SdEntry::new_service_entry(
1707 SdServiceEntryType::OfferService,
1708 0,
1709 0,
1710 0,
1711 0xFF,
1712 0,
1713 0,
1714 0,
1715 0,
1716 0,
1717 );
1718 assert_matches!(result, Err(SdValueError::NumberOfOption2TooLarge(0xFF)));
1719}
1720
1721#[test]
1722fn new_service_find_service_entry_zero_ttl() {
1723 use assert_matches::*;
1724
1725 let result = SdEntry::new_find_service_entry(0, 0, 0, 0, 0, 0, 0, 0, 0);
1726 assert_matches!(result, Err(SdValueError::TtlZeroIndicatesStopOffering));
1727}
1728
1729#[test]
1730fn new_service_offer_service_entry_zero_ttl() {
1731 use assert_matches::*;
1732
1733 let result = SdEntry::new_offer_service_entry(0, 0, 0, 0, 0, 0, 0, 0, 0);
1734 assert_matches!(result, Err(SdValueError::TtlZeroIndicatesStopOffering));
1735}