1#[cfg(feature = "std")]
41use std::error::Error;
42
43#[cfg(feature = "std")]
44use std::{fmt, time::Duration};
45
46#[cfg(not(feature = "std"))]
47use core::fmt;
48
49#[cfg(not(feature = "std"))]
50use alloc::{string::String, vec::Vec};
51
52#[cfg(not(feature = "std"))]
53use core::time::Duration;
54
55use crate::encoding::{decode_enumerated, encode_enumerated};
56use crate::object::Segmentation;
57use crate::service::{AbortReason, ConfirmedServiceChoice, RejectReason, UnconfirmedServiceChoice};
58
59#[cfg(feature = "std")]
61pub type Result<T> = std::result::Result<T, ApplicationError>;
62
63#[cfg(not(feature = "std"))]
64pub type Result<T> = core::result::Result<T, ApplicationError>;
65
66#[derive(Debug)]
68pub enum ApplicationError {
69 InvalidApdu(String),
71 UnsupportedApduType,
73 SegmentationError(String),
75 TransactionError(String),
77 ServiceError(String),
79 Timeout,
81 MaxApduLengthExceeded,
83}
84
85impl fmt::Display for ApplicationError {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 match self {
88 ApplicationError::InvalidApdu(msg) => write!(f, "Invalid APDU: {}", msg),
89 ApplicationError::UnsupportedApduType => write!(f, "Unsupported APDU type"),
90 ApplicationError::SegmentationError(msg) => write!(f, "Segmentation error: {}", msg),
91 ApplicationError::TransactionError(msg) => write!(f, "Transaction error: {}", msg),
92 ApplicationError::ServiceError(msg) => write!(f, "Service error: {}", msg),
93 ApplicationError::Timeout => write!(f, "Application timeout"),
94 ApplicationError::MaxApduLengthExceeded => write!(f, "Maximum APDU length exceeded"),
95 }
96 }
97}
98
99#[cfg(feature = "std")]
100impl Error for ApplicationError {}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104#[repr(u8)]
105pub enum ApduType {
106 ConfirmedRequest = 0,
107 UnconfirmedRequest = 1,
108 SimpleAck = 2,
109 ComplexAck = 3,
110 SegmentAck = 4,
111 Error = 5,
112 Reject = 6,
113 Abort = 7,
114}
115
116#[derive(Debug, Clone)]
118pub enum Apdu {
119 ConfirmedRequest {
121 segmented: bool,
122 more_follows: bool,
123 segmented_response_accepted: bool,
124 max_segments: MaxSegments,
125 max_response_size: MaxApduSize,
126 invoke_id: u8,
127 sequence_number: Option<u8>,
128 proposed_window_size: Option<u8>,
129 service_choice: ConfirmedServiceChoice,
130 service_data: Vec<u8>,
131 },
132
133 UnconfirmedRequest {
135 service_choice: UnconfirmedServiceChoice,
136 service_data: Vec<u8>,
137 },
138
139 SimpleAck { invoke_id: u8, service_choice: u8 },
141
142 ComplexAck {
144 segmented: bool,
145 more_follows: bool,
146 invoke_id: u8,
147 sequence_number: Option<u8>,
148 proposed_window_size: Option<u8>,
149 service_choice: ConfirmedServiceChoice,
150 service_data: Vec<u8>,
151 },
152
153 SegmentAck {
155 negative: bool,
156 server: bool,
157 invoke_id: u8,
158 sequence_number: u8,
159 window_size: u8,
160 },
161
162 Error {
164 invoke_id: u8,
165 service_choice: ConfirmedServiceChoice,
166 error_class: u8,
167 error_code: u8,
168 },
169
170 Reject {
172 invoke_id: u8,
173 reject_reason: RejectReason,
174 },
175
176 Abort {
178 server: bool,
179 invoke_id: u8,
180 abort_reason: u8,
181 },
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186pub enum MaxSegments {
187 Unspecified = 0,
188 Two = 1,
189 Four = 2,
190 Eight = 3,
191 Sixteen = 4,
192 ThirtyTwo = 5,
193 SixtyFour = 6,
194 GreaterThan64 = 7,
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum MaxApduSize {
200 Up50 = 0,
201 Up128 = 1,
202 Up206 = 2,
203 Up480 = 3,
204 Up1024 = 4,
205 Up1476 = 5,
206}
207
208impl MaxApduSize {
209 pub fn size(&self) -> usize {
211 match self {
212 MaxApduSize::Up50 => 50,
213 MaxApduSize::Up128 => 128,
214 MaxApduSize::Up206 => 206,
215 MaxApduSize::Up480 => 480,
216 MaxApduSize::Up1024 => 1024,
217 MaxApduSize::Up1476 => 1476,
218 }
219 }
220}
221
222#[derive(Debug, Clone)]
224pub struct Transaction {
225 pub invoke_id: u8,
227 pub service: u8,
229 pub state: TransactionState,
231 pub timeout: Duration,
233 pub retries: u8,
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub enum TransactionState {
240 AwaitConfirmation,
242 AwaitSegment,
244 SegmentedRequest,
246 SegmentedResponse,
248 Complete,
250}
251
252impl Apdu {
253 pub fn encode(&self) -> Vec<u8> {
255 let mut buffer = Vec::new();
256
257 match self {
258 Apdu::ConfirmedRequest {
259 segmented,
260 more_follows,
261 segmented_response_accepted,
262 max_segments,
263 max_response_size,
264 invoke_id,
265 sequence_number,
266 proposed_window_size,
267 service_choice,
268 service_data,
269 } => {
270 let mut pdu_type = (ApduType::ConfirmedRequest as u8) << 4;
272 if *segmented {
273 pdu_type |= 0x08;
274 }
275 if *more_follows {
276 pdu_type |= 0x04;
277 }
278 if *segmented_response_accepted {
279 pdu_type |= 0x02;
280 }
281 buffer.push(pdu_type);
282
283 let max_info = ((*max_segments as u8) << 4) | (*max_response_size as u8);
285 buffer.push(max_info);
286
287 buffer.push(*invoke_id);
289
290 if *segmented {
292 if let Some(seq_num) = sequence_number {
293 buffer.push(*seq_num);
294 }
295 if let Some(window_size) = proposed_window_size {
296 buffer.push(*window_size);
297 }
298 }
299
300 buffer.push(*service_choice as u8);
302
303 buffer.extend_from_slice(service_data);
305 }
306
307 Apdu::UnconfirmedRequest {
308 service_choice,
309 service_data,
310 } => {
311 buffer.push((ApduType::UnconfirmedRequest as u8) << 4);
313 buffer.push(*service_choice as u8);
315 buffer.extend_from_slice(service_data);
317 }
318
319 Apdu::SimpleAck {
320 invoke_id,
321 service_choice,
322 } => {
323 buffer.push((ApduType::SimpleAck as u8) << 4);
325 buffer.push(*invoke_id);
327 buffer.push(*service_choice);
329 }
330
331 Apdu::ComplexAck {
332 segmented,
333 more_follows,
334 invoke_id,
335 sequence_number,
336 proposed_window_size,
337 service_choice,
338 service_data,
339 } => {
340 let mut pdu_type = (ApduType::ComplexAck as u8) << 4;
342 if *segmented {
343 pdu_type |= 0x08;
344 }
345 if *more_follows {
346 pdu_type |= 0x04;
347 }
348 buffer.push(pdu_type);
349
350 buffer.push(*invoke_id);
352
353 if *segmented {
355 if let Some(seq_num) = sequence_number {
356 buffer.push(*seq_num);
357 }
358 if let Some(window_size) = proposed_window_size {
359 buffer.push(*window_size);
360 }
361 }
362
363 buffer.push(*service_choice as u8);
365
366 buffer.extend_from_slice(service_data);
368 }
369
370 Apdu::SegmentAck {
371 negative,
372 server,
373 invoke_id,
374 sequence_number,
375 window_size,
376 } => {
377 let mut pdu_type = (ApduType::SegmentAck as u8) << 4;
379 if *negative {
380 pdu_type |= 0x02;
381 }
382 if *server {
383 pdu_type |= 0x01;
384 }
385 buffer.push(pdu_type);
386
387 buffer.push(*invoke_id);
389 buffer.push(*sequence_number);
391 buffer.push(*window_size);
393 }
394
395 Apdu::Error {
396 invoke_id,
397 service_choice,
398 error_class,
399 error_code,
400 } => {
401 buffer.push((ApduType::Error as u8) << 4);
403 buffer.push(*invoke_id);
405 buffer.push(*service_choice as u8);
407 encode_enumerated(&mut buffer, *error_class as u32);
408 encode_enumerated(&mut buffer, *error_code as u32);
409 }
410
411 Apdu::Reject {
412 invoke_id,
413 reject_reason,
414 } => {
415 buffer.push((ApduType::Reject as u8) << 4);
417 buffer.push(*invoke_id);
419 buffer.push(u8::from(*reject_reason));
421 }
422
423 Apdu::Abort {
424 server,
425 invoke_id,
426 abort_reason,
427 } => {
428 let mut pdu_type = (ApduType::Abort as u8) << 4;
430 if *server {
431 pdu_type |= 0x01;
432 }
433 buffer.push(pdu_type);
434
435 buffer.push(*invoke_id);
437 buffer.push(*abort_reason);
439 }
440 }
441
442 buffer
443 }
444
445 pub fn decode(data: &[u8]) -> Result<Self> {
447 if data.is_empty() {
448 return Err(ApplicationError::InvalidApdu("Empty APDU".to_string()));
449 }
450
451 let pdu_type_byte = data[0];
452 let pdu_type_raw = (pdu_type_byte >> 4) & 0x0F;
453 let pdu_type = match pdu_type_raw {
454 0 => ApduType::ConfirmedRequest,
455 1 => ApduType::UnconfirmedRequest,
456 2 => ApduType::SimpleAck,
457 3 => ApduType::ComplexAck,
458 4 => ApduType::SegmentAck,
459 5 => ApduType::Error,
460 6 => ApduType::Reject,
461 7 => ApduType::Abort,
462 _ => return Err(ApplicationError::UnsupportedApduType),
463 };
464
465 match pdu_type {
466 ApduType::ConfirmedRequest => {
467 if data.len() < 4 {
468 return Err(ApplicationError::InvalidApdu(
469 "Confirmed request too short".to_string(),
470 ));
471 }
472
473 let segmented = (pdu_type_byte & 0x08) != 0;
474 let more_follows = (pdu_type_byte & 0x04) != 0;
475 let segmented_response_accepted = (pdu_type_byte & 0x02) != 0;
476
477 let max_info = data[1];
478 let max_segments = match (max_info >> 4) & 0x07 {
479 0 => MaxSegments::Unspecified,
480 1 => MaxSegments::Two,
481 2 => MaxSegments::Four,
482 3 => MaxSegments::Eight,
483 4 => MaxSegments::Sixteen,
484 5 => MaxSegments::ThirtyTwo,
485 6 => MaxSegments::SixtyFour,
486 7 => MaxSegments::GreaterThan64,
487 _ => MaxSegments::Unspecified,
488 };
489
490 let max_response_size = match max_info & 0x0F {
491 0 => MaxApduSize::Up50,
492 1 => MaxApduSize::Up128,
493 2 => MaxApduSize::Up206,
494 3 => MaxApduSize::Up480,
495 4 => MaxApduSize::Up1024,
496 5 => MaxApduSize::Up1476,
497 _ => MaxApduSize::Up50,
498 };
499
500 let invoke_id = data[2];
501 let mut pos = 3;
502
503 let (sequence_number, proposed_window_size) = if segmented {
504 let seq_num = if pos < data.len() {
505 Some(data[pos])
506 } else {
507 None
508 };
509 pos += 1;
510 let win_size = if pos < data.len() {
511 Some(data[pos])
512 } else {
513 None
514 };
515 pos += 1;
516 (seq_num, win_size)
517 } else {
518 (None, None)
519 };
520
521 if pos >= data.len() {
522 return Err(ApplicationError::InvalidApdu(
523 "Missing service choice".to_string(),
524 ));
525 }
526
527 let service_choice = data[pos].try_into().map_err(|_| {
528 ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
529 })?;
530 pos += 1;
531
532 let service_data = if pos < data.len() {
533 data[pos..].to_vec()
534 } else {
535 Vec::new()
536 };
537
538 Ok(Apdu::ConfirmedRequest {
539 segmented,
540 more_follows,
541 segmented_response_accepted,
542 max_segments,
543 max_response_size,
544 invoke_id,
545 sequence_number,
546 proposed_window_size,
547 service_choice,
548 service_data,
549 })
550 }
551
552 ApduType::UnconfirmedRequest => {
553 if data.len() < 2 {
554 return Err(ApplicationError::InvalidApdu(
555 "Unconfirmed request too short".to_string(),
556 ));
557 }
558
559 let service_choice = data[1];
560 let service_data = if data.len() > 2 {
561 data[2..].to_vec()
562 } else {
563 Vec::new()
564 };
565
566 Ok(Apdu::UnconfirmedRequest {
567 service_choice: service_choice.try_into().map_err(|_| {
568 ApplicationError::InvalidApdu(
569 "Unknown unconfirmed service choice".to_string(),
570 )
571 })?,
572 service_data,
573 })
574 }
575
576 ApduType::SimpleAck => {
577 if data.len() < 3 {
578 return Err(ApplicationError::InvalidApdu(
579 "SimpleAck too short".to_string(),
580 ));
581 }
582
583 let invoke_id = data[1];
584 let service_choice = data[2];
585
586 Ok(Apdu::SimpleAck {
587 invoke_id,
588 service_choice,
589 })
590 }
591
592 ApduType::ComplexAck => {
593 if data.len() < 3 {
594 return Err(ApplicationError::InvalidApdu(
595 "ComplexAck too short".to_string(),
596 ));
597 }
598
599 let segmented = (pdu_type_byte & 0x08) != 0;
600 let more_follows = (pdu_type_byte & 0x04) != 0;
601
602 let invoke_id = data[1];
603 let mut pos = 2;
604
605 let (sequence_number, proposed_window_size) = if segmented {
606 let seq_num = if pos < data.len() {
607 Some(data[pos])
608 } else {
609 None
610 };
611 pos += 1;
612 let win_size = if pos < data.len() {
613 Some(data[pos])
614 } else {
615 None
616 };
617 pos += 1;
618 (seq_num, win_size)
619 } else {
620 (None, None)
621 };
622
623 if pos >= data.len() {
624 return Err(ApplicationError::InvalidApdu(
625 "Missing service choice".to_string(),
626 ));
627 }
628
629 let service_choice = data[pos].try_into().map_err(|_| {
630 ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
631 })?;
632 pos += 1;
633
634 let service_data = if pos < data.len() {
635 data[pos..].to_vec()
636 } else {
637 Vec::new()
638 };
639
640 Ok(Apdu::ComplexAck {
641 segmented,
642 more_follows,
643 invoke_id,
644 sequence_number,
645 proposed_window_size,
646 service_choice,
647 service_data,
648 })
649 }
650
651 ApduType::SegmentAck => {
652 if data.len() < 4 {
653 return Err(ApplicationError::InvalidApdu(
654 "SegmentAck too short".to_string(),
655 ));
656 }
657
658 let negative = (pdu_type_byte & 0x02) != 0;
659 let server = (pdu_type_byte & 0x01) != 0;
660 let invoke_id = data[1];
661 let sequence_number = data[2];
662 let window_size = data[3];
663
664 Ok(Apdu::SegmentAck {
665 negative,
666 server,
667 invoke_id,
668 sequence_number,
669 window_size,
670 })
671 }
672
673 ApduType::Error => {
674 if data.len() < 5 {
675 return Err(ApplicationError::InvalidApdu(
676 "Error PDU too short".to_string(),
677 ));
678 }
679
680 let invoke_id = data[1];
681 let mut pos = 2;
682 let service_choice = data[pos].try_into().map_err(|_| {
683 ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
684 })?;
685 pos += 1;
686 let (error_class, offset) = decode_enumerated(&data[pos..]).map_err(|_| {
687 ApplicationError::InvalidApdu("Invalid error class".to_string())
688 })?;
689 pos += offset;
690 let (error_code, _) = decode_enumerated(&data[pos..])
691 .map_err(|_| ApplicationError::InvalidApdu("Invalid error code".to_string()))?;
692
693 Ok(Apdu::Error {
694 invoke_id,
695 service_choice,
696 error_class: error_class as u8,
697 error_code: error_code as u8,
698 })
699 }
700
701 ApduType::Reject => {
702 if data.len() < 3 {
703 return Err(ApplicationError::InvalidApdu(
704 "Reject PDU too short".to_string(),
705 ));
706 }
707
708 let invoke_id = data[1];
709 let reject_reason = data[2];
710
711 Ok(Apdu::Reject {
712 invoke_id,
713 reject_reason: reject_reason.into(),
714 })
715 }
716
717 ApduType::Abort => {
718 if data.len() < 3 {
719 return Err(ApplicationError::InvalidApdu(
720 "Abort PDU too short".to_string(),
721 ));
722 }
723
724 let server = (pdu_type_byte & 0x01) != 0;
725 let invoke_id = data[1];
726 let abort_reason = data[2];
727
728 Ok(Apdu::Abort {
729 server,
730 invoke_id,
731 abort_reason,
732 })
733 }
734 }
735 }
736}
737
738#[derive(Debug)]
740pub struct InvokeIdManager {
741 next_id: u8,
742 active_ids: Vec<u8>,
743}
744
745impl InvokeIdManager {
746 pub fn new() -> Self {
748 Self {
749 next_id: 0,
750 active_ids: Vec::new(),
751 }
752 }
753
754 pub fn next_id(&mut self) -> Option<u8> {
756 let start_id = self.next_id;
757
758 loop {
759 if !self.active_ids.contains(&self.next_id) {
760 let id = self.next_id;
761 self.active_ids.push(id);
762 self.next_id = self.next_id.wrapping_add(1);
763 return Some(id);
764 }
765
766 self.next_id = self.next_id.wrapping_add(1);
767
768 if self.next_id == start_id {
770 return None;
771 }
772 }
773 }
774
775 pub fn release_id(&mut self, id: u8) {
777 self.active_ids.retain(|&x| x != id);
778 }
779
780 pub fn is_active(&self, id: u8) -> bool {
782 self.active_ids.contains(&id)
783 }
784}
785
786impl Default for InvokeIdManager {
787 fn default() -> Self {
788 Self::new()
789 }
790}
791
792#[derive(Debug, Clone, PartialEq, Eq)]
794pub struct SegmentationInfo {
795 pub more_follows: bool,
797 pub segmented_response_accepted: bool,
799 pub max_segments_accepted: u8,
801 pub max_apdu_length_accepted: u16,
803 pub sequence_number: u8,
805 pub proposed_window_size: u8,
807}
808
809impl SegmentationInfo {
810 pub fn new(
812 more_follows: bool,
813 segmented_response_accepted: bool,
814 max_segments_accepted: u8,
815 max_apdu_length_accepted: u16,
816 sequence_number: u8,
817 proposed_window_size: u8,
818 ) -> Self {
819 Self {
820 more_follows,
821 segmented_response_accepted,
822 max_segments_accepted,
823 max_apdu_length_accepted,
824 sequence_number,
825 proposed_window_size,
826 }
827 }
828
829 pub fn is_first_segment(&self) -> bool {
831 self.sequence_number == 0
832 }
833
834 pub fn is_last_segment(&self) -> bool {
836 !self.more_follows
837 }
838
839 pub fn max_segment_size(&self) -> usize {
841 (self.max_apdu_length_accepted as usize).saturating_sub(6)
843 }
844}
845
846#[derive(Debug)]
848pub struct SegmentReassemblyBuffer {
849 pub invoke_id: u8,
851 pub total_segments: Option<u8>,
853 pub segments: Vec<(u8, Vec<u8>)>,
855 pub max_apdu_length: u16,
857 #[cfg(feature = "std")]
859 pub last_activity: std::time::Instant,
860}
861
862impl SegmentReassemblyBuffer {
863 pub fn new(invoke_id: u8, max_apdu_length: u16) -> Self {
865 Self {
866 invoke_id,
867 total_segments: None,
868 segments: Vec::new(),
869 max_apdu_length,
870 #[cfg(feature = "std")]
871 last_activity: std::time::Instant::now(),
872 }
873 }
874
875 pub fn add_segment(&mut self, sequence_number: u8, data: Vec<u8>, is_last: bool) -> Result<()> {
877 #[cfg(feature = "std")]
879 {
880 self.last_activity = std::time::Instant::now();
881 }
882
883 if is_last {
885 self.total_segments = Some(sequence_number + 1);
886 }
887
888 if self.segments.iter().any(|(seq, _)| *seq == sequence_number) {
890 return Ok(()); }
892
893 self.segments.push((sequence_number, data));
895
896 self.segments.sort_by_key(|(seq, _)| *seq);
898
899 Ok(())
900 }
901
902 pub fn is_complete(&self) -> bool {
904 if let Some(total) = self.total_segments {
905 self.segments.len() == total as usize
906 && self
907 .segments
908 .iter()
909 .enumerate()
910 .all(|(i, (seq, _))| *seq == i as u8)
911 } else {
912 false
913 }
914 }
915
916 pub fn reassemble(&self) -> Result<Vec<u8>> {
918 if !self.is_complete() {
919 return Err(ApplicationError::SegmentationError(
920 "Incomplete segments".to_string(),
921 ));
922 }
923
924 let mut result = Vec::new();
925 for (_, data) in &self.segments {
926 result.extend_from_slice(data);
927 }
928
929 if result.len() > self.max_apdu_length as usize {
930 return Err(ApplicationError::MaxApduLengthExceeded);
931 }
932
933 Ok(result)
934 }
935
936 pub fn missing_segments(&self) -> Vec<u8> {
938 if let Some(total) = self.total_segments {
939 let mut missing = Vec::new();
940 for i in 0..total {
941 if !self.segments.iter().any(|(seq, _)| *seq == i) {
942 missing.push(i);
943 }
944 }
945 missing
946 } else {
947 Vec::new()
948 }
949 }
950
951 #[cfg(feature = "std")]
953 pub fn is_timed_out(&self, timeout_duration: std::time::Duration) -> bool {
954 self.last_activity.elapsed() > timeout_duration
955 }
956}
957
958#[derive(Debug)]
960pub struct SegmentationManager {
961 reassembly_buffers: Vec<SegmentReassemblyBuffer>,
963 max_concurrent_reassemblies: usize,
965 #[cfg(feature = "std")]
967 segment_timeout: std::time::Duration,
968}
969
970impl SegmentationManager {
971 pub fn new() -> Self {
973 Self {
974 reassembly_buffers: Vec::new(),
975 max_concurrent_reassemblies: 16,
976 #[cfg(feature = "std")]
977 segment_timeout: std::time::Duration::from_secs(60),
978 }
979 }
980
981 pub fn segment_message(
983 &self,
984 data: &[u8],
985 max_segment_size: usize,
986 max_segments: u8,
987 ) -> Result<Vec<Vec<u8>>> {
988 if data.is_empty() {
989 return Ok(vec![Vec::new()]);
990 }
991
992 let segment_count = data.len().div_ceil(max_segment_size);
993
994 if segment_count > max_segments as usize {
995 return Err(ApplicationError::SegmentationError(
996 "Message too large for segmentation".to_string(),
997 ));
998 }
999
1000 let mut segments = Vec::new();
1001 let mut offset = 0;
1002
1003 for _ in 0..segment_count {
1004 let end = (offset + max_segment_size).min(data.len());
1005 segments.push(data[offset..end].to_vec());
1006 offset = end;
1007 }
1008
1009 Ok(segments)
1010 }
1011
1012 pub fn process_segment(
1014 &mut self,
1015 invoke_id: u8,
1016 sequence_number: u8,
1017 data: Vec<u8>,
1018 more_follows: bool,
1019 max_apdu_length: u16,
1020 ) -> Result<Option<Vec<u8>>> {
1021 let buffer_index = self
1023 .reassembly_buffers
1024 .iter()
1025 .position(|buffer| buffer.invoke_id == invoke_id);
1026
1027 let buffer = if let Some(index) = buffer_index {
1028 &mut self.reassembly_buffers[index]
1029 } else {
1030 if self.reassembly_buffers.len() >= self.max_concurrent_reassemblies {
1032 self.cleanup_oldest_buffer();
1034 }
1035
1036 self.reassembly_buffers
1037 .push(SegmentReassemblyBuffer::new(invoke_id, max_apdu_length));
1038 self.reassembly_buffers.last_mut().unwrap()
1039 };
1040
1041 buffer.add_segment(sequence_number, data, !more_follows)?;
1043
1044 if buffer.is_complete() {
1046 let result = buffer.reassemble()?;
1047 self.reassembly_buffers.retain(|b| b.invoke_id != invoke_id);
1049 Ok(Some(result))
1050 } else {
1051 Ok(None)
1052 }
1053 }
1054
1055 pub fn get_missing_segments(&self, invoke_id: u8) -> Vec<u8> {
1057 self.reassembly_buffers
1058 .iter()
1059 .find(|buffer| buffer.invoke_id == invoke_id)
1060 .map(|buffer| buffer.missing_segments())
1061 .unwrap_or_default()
1062 }
1063
1064 #[cfg(feature = "std")]
1066 pub fn cleanup_timed_out_buffers(&mut self) {
1067 self.reassembly_buffers
1068 .retain(|buffer| !buffer.is_timed_out(self.segment_timeout));
1069 }
1070
1071 fn cleanup_oldest_buffer(&mut self) {
1073 if !self.reassembly_buffers.is_empty() {
1074 #[cfg(feature = "std")]
1075 {
1076 let oldest_index = self
1078 .reassembly_buffers
1079 .iter()
1080 .enumerate()
1081 .min_by_key(|(_, buffer)| buffer.last_activity)
1082 .map(|(index, _)| index)
1083 .unwrap_or(0);
1084 self.reassembly_buffers.remove(oldest_index);
1085 }
1086 #[cfg(not(feature = "std"))]
1087 {
1088 self.reassembly_buffers.remove(0);
1090 }
1091 }
1092 }
1093
1094 #[cfg(feature = "std")]
1096 pub fn set_segment_timeout(&mut self, timeout: std::time::Duration) {
1097 self.segment_timeout = timeout;
1098 }
1099
1100 pub fn active_reassemblies(&self) -> usize {
1102 self.reassembly_buffers.len()
1103 }
1104}
1105
1106impl Default for SegmentationManager {
1107 fn default() -> Self {
1108 Self::new()
1109 }
1110}
1111
1112#[derive(Debug)]
1114pub struct ApplicationLayerHandler {
1115 _device_instance: u32,
1117 supported_services: SupportedServices,
1119 transaction_manager: TransactionManager,
1121 service_processors: ServiceProcessors,
1123 pub stats: ApplicationStatistics,
1125}
1126
1127#[derive(Debug, Clone)]
1129pub struct SupportedServices {
1130 pub confirmed: Vec<ConfirmedServiceChoice>,
1132 pub unconfirmed: Vec<UnconfirmedServiceChoice>,
1134}
1135
1136impl Default for SupportedServices {
1137 fn default() -> Self {
1138 Self {
1139 confirmed: vec![
1140 ConfirmedServiceChoice::ReadProperty,
1141 ConfirmedServiceChoice::WriteProperty,
1142 ConfirmedServiceChoice::ReadPropertyMultiple,
1143 ConfirmedServiceChoice::SubscribeCOV,
1144 ],
1145 unconfirmed: vec![
1146 UnconfirmedServiceChoice::WhoIs,
1147 UnconfirmedServiceChoice::IAm,
1148 UnconfirmedServiceChoice::UnconfirmedEventNotification,
1149 ],
1150 }
1151 }
1152}
1153
1154type ServiceProcessor = Box<dyn Fn(&[u8]) -> Result<Vec<u8>> + Send + Sync>;
1156
1157type OptionalServiceProcessor = Box<dyn Fn(&[u8]) -> Result<Option<Vec<u8>>> + Send + Sync>;
1159
1160#[derive(Default)]
1162struct ServiceProcessors {
1163 read_property: Option<ServiceProcessor>,
1165 write_property: Option<ServiceProcessor>,
1167 who_is: Option<OptionalServiceProcessor>,
1169}
1170
1171impl fmt::Debug for ServiceProcessors {
1172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173 f.debug_struct("ServiceProcessors")
1174 .field("read_property", &self.read_property.is_some())
1175 .field("write_property", &self.write_property.is_some())
1176 .field("who_is", &self.who_is.is_some())
1177 .finish()
1178 }
1179}
1180
1181impl ApplicationLayerHandler {
1182 pub fn new(device_instance: u32) -> Self {
1184 Self {
1185 _device_instance: device_instance,
1186 supported_services: SupportedServices::default(),
1187 transaction_manager: TransactionManager::new(),
1188 service_processors: ServiceProcessors::default(),
1189 stats: ApplicationStatistics::default(),
1190 }
1191 }
1192
1193 pub fn process_apdu(&mut self, apdu: &Apdu, _source: &[u8]) -> Result<Option<Apdu>> {
1195 self.stats.apdus_received += 1;
1196
1197 match apdu {
1198 Apdu::ConfirmedRequest {
1199 segmented,
1200 more_follows,
1201 segmented_response_accepted,
1202 max_segments: _,
1203 max_response_size: _,
1204 invoke_id,
1205 sequence_number: _,
1206 proposed_window_size: _,
1207 service_choice,
1208 service_data,
1209 } => {
1210 let pdu_flags = PduFlags {
1211 segmented: *segmented,
1212 more_follows: *more_follows,
1213 segmented_response_accepted: *segmented_response_accepted,
1214 };
1215 self.process_confirmed_request(pdu_flags, *invoke_id, *service_choice, service_data)
1216 }
1217 Apdu::UnconfirmedRequest {
1218 service_choice,
1219 service_data,
1220 } => self.process_unconfirmed_request(*service_choice, service_data),
1221 Apdu::SimpleAck {
1222 invoke_id,
1223 service_choice,
1224 } => self.process_simple_ack(*invoke_id, *service_choice),
1225 Apdu::ComplexAck {
1226 segmented,
1227 more_follows,
1228 invoke_id,
1229 sequence_number: _,
1230 proposed_window_size: _,
1231 service_choice,
1232 service_data,
1233 } => {
1234 let pdu_flags = PduFlags {
1235 segmented: *segmented,
1236 more_follows: *more_follows,
1237 segmented_response_accepted: false,
1238 };
1239 self.process_complex_ack(pdu_flags, *invoke_id, *service_choice, service_data)
1240 }
1241 Apdu::Error {
1242 invoke_id,
1243 service_choice,
1244 error_class,
1245 error_code,
1246 } => self.process_error(*invoke_id, *service_choice, *error_class, *error_code),
1247 Apdu::Reject {
1248 invoke_id,
1249 reject_reason,
1250 } => self.process_reject(*invoke_id, *reject_reason),
1251 Apdu::Abort {
1252 server,
1253 invoke_id,
1254 abort_reason,
1255 } => self.process_abort(*server, *invoke_id, *abort_reason),
1256 _ => {
1257 self.stats.unknown_apdus += 1;
1258 Err(ApplicationError::UnsupportedApduType)
1259 }
1260 }
1261 }
1262
1263 fn process_confirmed_request(
1265 &mut self,
1266 _pdu_flags: PduFlags,
1267 invoke_id: u8,
1268 service_choice: ConfirmedServiceChoice,
1269 service_data: &[u8],
1270 ) -> Result<Option<Apdu>> {
1271 self.stats.confirmed_requests += 1;
1272
1273 if !self.supported_services.confirmed.contains(&service_choice) {
1274 return Ok(Some(Apdu::Reject {
1275 invoke_id,
1276 reject_reason: RejectReason::UnrecognizedService,
1277 }));
1278 }
1279
1280 match service_choice {
1282 ConfirmedServiceChoice::ReadProperty => {
1283 if let Some(ref processor) = self.service_processors.read_property {
1284 match processor(service_data) {
1285 Ok(response_data) => Ok(Some(Apdu::ComplexAck {
1286 segmented: false,
1287 more_follows: false,
1288 invoke_id,
1289 sequence_number: None,
1290 proposed_window_size: None,
1291 service_choice,
1292 service_data: response_data,
1293 })),
1294 Err(_) => {
1295 Ok(Some(Apdu::Error {
1296 invoke_id,
1297 service_choice,
1298 error_class: 0, error_code: 0, }))
1301 }
1302 }
1303 } else {
1304 Ok(Some(Apdu::Abort {
1305 server: true,
1306 invoke_id,
1307 abort_reason: u8::from(AbortReason::Other),
1308 }))
1309 }
1310 }
1311 _ => Ok(Some(Apdu::Reject {
1312 invoke_id,
1313 reject_reason: RejectReason::UnrecognizedService,
1314 })),
1315 }
1316 }
1317
1318 fn process_unconfirmed_request(
1320 &mut self,
1321 service_choice: UnconfirmedServiceChoice,
1322 service_data: &[u8],
1323 ) -> Result<Option<Apdu>> {
1324 self.stats.unconfirmed_requests += 1;
1325
1326 if service_choice == UnconfirmedServiceChoice::WhoIs {
1328 if let Some(ref processor) = self.service_processors.who_is {
1329 if let Ok(Some(response_data)) = processor(service_data) {
1330 return Ok(Some(Apdu::UnconfirmedRequest {
1331 service_choice: UnconfirmedServiceChoice::IAm,
1332 service_data: response_data,
1333 }));
1334 }
1335 }
1336 }
1337
1338 Ok(None)
1339 }
1340
1341 fn process_simple_ack(&mut self, invoke_id: u8, _service_choice: u8) -> Result<Option<Apdu>> {
1343 self.stats.simple_acks += 1;
1344 self.transaction_manager.complete_transaction(invoke_id);
1345 Ok(None)
1346 }
1347
1348 fn process_complex_ack(
1350 &mut self,
1351 _pdu_flags: PduFlags,
1352 invoke_id: u8,
1353 _service_choice: ConfirmedServiceChoice,
1354 _service_data: &[u8],
1355 ) -> Result<Option<Apdu>> {
1356 self.stats.complex_acks += 1;
1357 self.transaction_manager.complete_transaction(invoke_id);
1358 Ok(None)
1359 }
1360
1361 fn process_error(
1363 &mut self,
1364 invoke_id: u8,
1365 _service_choice: ConfirmedServiceChoice,
1366 error_class: u8,
1367 error_code: u8,
1368 ) -> Result<Option<Apdu>> {
1369 self.stats.errors += 1;
1370 self.transaction_manager
1371 .error_transaction(invoke_id, error_class, error_code);
1372 Ok(None)
1373 }
1374
1375 fn process_reject(
1377 &mut self,
1378 invoke_id: u8,
1379 reject_reason: RejectReason,
1380 ) -> Result<Option<Apdu>> {
1381 self.stats.rejects += 1;
1382 self.transaction_manager
1383 .reject_transaction(invoke_id, reject_reason);
1384 Ok(None)
1385 }
1386
1387 fn process_abort(
1389 &mut self,
1390 _server: bool,
1391 invoke_id: u8,
1392 abort_reason: u8,
1393 ) -> Result<Option<Apdu>> {
1394 self.stats.aborts += 1;
1395 self.transaction_manager
1396 .abort_transaction(invoke_id, abort_reason);
1397 Ok(None)
1398 }
1399
1400 pub fn set_read_property_handler<F>(&mut self, handler: F)
1402 where
1403 F: Fn(&[u8]) -> Result<Vec<u8>> + Send + Sync + 'static,
1404 {
1405 self.service_processors.read_property = Some(Box::new(handler));
1406 }
1407
1408 pub fn set_who_is_handler<F>(&mut self, handler: F)
1410 where
1411 F: Fn(&[u8]) -> Result<Option<Vec<u8>>> + Send + Sync + 'static,
1412 {
1413 self.service_processors.who_is = Some(Box::new(handler));
1414 }
1415}
1416
1417#[derive(Debug)]
1419pub struct TransactionManager {
1420 transactions: Vec<Transaction>,
1422 max_transactions: usize,
1424 #[cfg(feature = "std")]
1426 _timeout: Duration,
1427}
1428
1429impl TransactionManager {
1430 pub fn new() -> Self {
1432 Self {
1433 transactions: Vec::new(),
1434 max_transactions: 255,
1435 #[cfg(feature = "std")]
1436 _timeout: Duration::from_secs(30),
1437 }
1438 }
1439
1440 pub fn start_transaction(&mut self, invoke_id: u8, service_choice: u8) -> Result<()> {
1442 if self.transactions.len() >= self.max_transactions {
1443 return Err(ApplicationError::TransactionError(
1444 "Too many active transactions".to_string(),
1445 ));
1446 }
1447
1448 if self
1450 .transactions
1451 .iter()
1452 .any(|t| t.invoke_id == invoke_id && t.state == TransactionState::AwaitConfirmation)
1453 {
1454 return Err(ApplicationError::TransactionError(
1455 "Duplicate invoke ID".to_string(),
1456 ));
1457 }
1458
1459 self.transactions.push(Transaction {
1460 invoke_id,
1461 service: service_choice,
1462 state: TransactionState::AwaitConfirmation,
1463 timeout: Duration::from_secs(30),
1464 retries: 0,
1465 });
1466
1467 Ok(())
1468 }
1469
1470 pub fn complete_transaction(&mut self, invoke_id: u8) {
1472 if let Some(transaction) = self
1473 .transactions
1474 .iter_mut()
1475 .find(|t| t.invoke_id == invoke_id)
1476 {
1477 transaction.state = TransactionState::Complete;
1478 }
1479 }
1480
1481 pub fn error_transaction(&mut self, invoke_id: u8, _error_class: u8, _error_code: u8) {
1483 if let Some(transaction) = self
1484 .transactions
1485 .iter_mut()
1486 .find(|t| t.invoke_id == invoke_id)
1487 {
1488 transaction.state = TransactionState::Complete;
1489 }
1490 }
1491
1492 pub fn reject_transaction(&mut self, invoke_id: u8, _reject_reason: RejectReason) {
1494 if let Some(transaction) = self
1495 .transactions
1496 .iter_mut()
1497 .find(|t| t.invoke_id == invoke_id)
1498 {
1499 transaction.state = TransactionState::Complete;
1500 }
1501 }
1502
1503 pub fn abort_transaction(&mut self, invoke_id: u8, _abort_reason: u8) {
1505 if let Some(transaction) = self
1506 .transactions
1507 .iter_mut()
1508 .find(|t| t.invoke_id == invoke_id)
1509 {
1510 transaction.state = TransactionState::Complete;
1511 }
1512 }
1513
1514 pub fn cleanup_completed(&mut self) {
1516 self.transactions
1517 .retain(|t| t.state != TransactionState::Complete);
1518 }
1519
1520 pub fn active_count(&self) -> usize {
1522 self.transactions
1523 .iter()
1524 .filter(|t| t.state != TransactionState::Complete)
1525 .count()
1526 }
1527}
1528
1529impl Default for TransactionManager {
1530 fn default() -> Self {
1531 Self::new()
1532 }
1533}
1534
1535#[derive(Debug, Default)]
1537pub struct ApplicationStatistics {
1538 pub apdus_received: u64,
1540 pub apdus_sent: u64,
1542 pub confirmed_requests: u64,
1544 pub unconfirmed_requests: u64,
1546 pub simple_acks: u64,
1548 pub complex_acks: u64,
1550 pub errors: u64,
1552 pub rejects: u64,
1554 pub aborts: u64,
1556 pub unknown_apdus: u64,
1558 pub segmentation_errors: u64,
1560}
1561
1562#[derive(Debug)]
1564pub struct ApplicationPriorityQueue {
1565 high: Vec<QueuedMessage>,
1567 normal: Vec<QueuedMessage>,
1569 low: Vec<QueuedMessage>,
1571 max_queue_size: usize,
1573}
1574
1575#[derive(Debug)]
1577struct QueuedMessage {
1578 apdu: Apdu,
1580 destination: Vec<u8>,
1582 #[cfg(feature = "std")]
1584 _timestamp: std::time::Instant,
1585 _retry_count: u8,
1587}
1588
1589impl ApplicationPriorityQueue {
1590 pub fn new(max_queue_size: usize) -> Self {
1592 Self {
1593 high: Vec::with_capacity(max_queue_size),
1594 normal: Vec::with_capacity(max_queue_size),
1595 low: Vec::with_capacity(max_queue_size),
1596 max_queue_size,
1597 }
1598 }
1599
1600 pub fn enqueue(
1602 &mut self,
1603 apdu: Apdu,
1604 destination: Vec<u8>,
1605 priority: MessagePriority,
1606 ) -> Result<()> {
1607 let queue = match priority {
1608 MessagePriority::High => &mut self.high,
1609 MessagePriority::Normal => &mut self.normal,
1610 MessagePriority::Low => &mut self.low,
1611 };
1612
1613 if queue.len() >= self.max_queue_size {
1614 return Err(ApplicationError::TransactionError("Queue full".to_string()));
1615 }
1616
1617 queue.push(QueuedMessage {
1618 apdu,
1619 destination,
1620 #[cfg(feature = "std")]
1621 _timestamp: std::time::Instant::now(),
1622 _retry_count: 0,
1623 });
1624
1625 Ok(())
1626 }
1627
1628 pub fn dequeue(&mut self) -> Option<(Apdu, Vec<u8>)> {
1630 if let Some(msg) = self.high.pop() {
1631 return Some((msg.apdu, msg.destination));
1632 }
1633 if let Some(msg) = self.normal.pop() {
1634 return Some((msg.apdu, msg.destination));
1635 }
1636 if let Some(msg) = self.low.pop() {
1637 return Some((msg.apdu, msg.destination));
1638 }
1639 None
1640 }
1641
1642 pub fn total_queued(&self) -> usize {
1644 self.high.len() + self.normal.len() + self.low.len()
1645 }
1646
1647 pub fn clear(&mut self) {
1649 self.high.clear();
1650 self.normal.clear();
1651 self.low.clear();
1652 }
1653}
1654
1655#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1657pub enum MessagePriority {
1658 High,
1660 Normal,
1662 Low,
1664}
1665
1666#[derive(Debug, Clone, Copy, Default)]
1668pub struct PduFlags {
1669 pub segmented: bool,
1671 pub more_follows: bool,
1673 pub segmented_response_accepted: bool,
1675}
1676
1677#[derive(Debug, Clone)]
1679pub struct ApplicationConfig {
1680 pub max_apdu_length: u16,
1682 pub segmentation: Segmentation,
1684 pub apdu_timeout: u16,
1686 pub apdu_retries: u8,
1688 pub max_segments: u8,
1690 pub invoke_id_start: u8,
1692}
1693
1694impl Default for ApplicationConfig {
1695 fn default() -> Self {
1696 Self {
1697 max_apdu_length: 1476,
1698 segmentation: Segmentation::Both,
1699 apdu_timeout: 6000,
1700 apdu_retries: 3,
1701 max_segments: 64,
1702 invoke_id_start: 0,
1703 }
1704 }
1705}
1706
1707#[cfg(test)]
1708mod tests {
1709 use super::*;
1710
1711 #[test]
1712 fn test_unconfirmed_request_encode_decode() {
1713 let apdu = Apdu::UnconfirmedRequest {
1714 service_choice: UnconfirmedServiceChoice::WhoIs, service_data: vec![0x08, 0x7B, 0x18, 0x7B], };
1717
1718 let encoded = apdu.encode();
1719 let decoded = Apdu::decode(&encoded).unwrap();
1720
1721 match decoded {
1722 Apdu::UnconfirmedRequest {
1723 service_choice,
1724 service_data,
1725 } => {
1726 assert_eq!(service_choice, UnconfirmedServiceChoice::WhoIs);
1727 assert_eq!(service_data, vec![0x08, 0x7B, 0x18, 0x7B]);
1728 }
1729 _ => panic!("Expected UnconfirmedRequest"),
1730 }
1731 }
1732
1733 #[test]
1734 fn test_simple_ack_encode_decode() {
1735 let apdu = Apdu::SimpleAck {
1736 invoke_id: 42,
1737 service_choice: 12, };
1739
1740 let encoded = apdu.encode();
1741 let decoded = Apdu::decode(&encoded).unwrap();
1742
1743 match decoded {
1744 Apdu::SimpleAck {
1745 invoke_id,
1746 service_choice,
1747 } => {
1748 assert_eq!(invoke_id, 42);
1749 assert_eq!(service_choice, 12);
1750 }
1751 _ => panic!("Expected SimpleAck"),
1752 }
1753 }
1754
1755 #[test]
1756 fn test_confirmed_request_encode_decode() {
1757 let apdu = Apdu::ConfirmedRequest {
1758 segmented: false,
1759 more_follows: false,
1760 segmented_response_accepted: true,
1761 max_segments: MaxSegments::Unspecified,
1762 max_response_size: MaxApduSize::Up1476,
1763 invoke_id: 123,
1764 sequence_number: None,
1765 proposed_window_size: None,
1766 service_choice: ConfirmedServiceChoice::ReadProperty, service_data: vec![0x0C, 0x02, 0x00, 0x00, 0x08, 0x19, 0x55],
1768 };
1769
1770 let encoded = apdu.encode();
1771 let decoded = Apdu::decode(&encoded).unwrap();
1772
1773 match decoded {
1774 Apdu::ConfirmedRequest {
1775 invoke_id,
1776 service_choice,
1777 segmented_response_accepted,
1778 ..
1779 } => {
1780 assert_eq!(invoke_id, 123);
1781 assert_eq!(service_choice, ConfirmedServiceChoice::ReadProperty);
1782 assert!(segmented_response_accepted);
1783 }
1784 _ => panic!("Expected ConfirmedRequest"),
1785 }
1786 }
1787
1788 #[test]
1789 fn test_invoke_id_manager() {
1790 let mut manager = InvokeIdManager::new();
1791
1792 let id1 = manager.next_id().unwrap();
1794 let id2 = manager.next_id().unwrap();
1795 let id3 = manager.next_id().unwrap();
1796
1797 assert_ne!(id1, id2);
1798 assert_ne!(id2, id3);
1799 assert_ne!(id1, id3);
1800
1801 assert!(manager.is_active(id1));
1803 assert!(manager.is_active(id2));
1804 assert!(manager.is_active(id3));
1805
1806 manager.release_id(id2);
1808 assert!(!manager.is_active(id2));
1809 assert!(manager.is_active(id1));
1810 assert!(manager.is_active(id3));
1811 }
1812
1813 #[test]
1814 fn test_max_apdu_size() {
1815 assert_eq!(MaxApduSize::Up50.size(), 50);
1816 assert_eq!(MaxApduSize::Up128.size(), 128);
1817 assert_eq!(MaxApduSize::Up1476.size(), 1476);
1818 }
1819
1820 #[test]
1821 fn test_segmentation_info() {
1822 let seg_info = SegmentationInfo::new(
1823 true, true, 64, 1476, 5, 10, );
1830
1831 assert!(seg_info.more_follows);
1832 assert!(seg_info.segmented_response_accepted);
1833 assert_eq!(seg_info.max_segments_accepted, 64);
1834 assert_eq!(seg_info.max_apdu_length_accepted, 1476);
1835 assert_eq!(seg_info.sequence_number, 5);
1836 assert_eq!(seg_info.proposed_window_size, 10);
1837
1838 assert!(!seg_info.is_first_segment());
1839 assert!(!seg_info.is_last_segment());
1840 assert_eq!(seg_info.max_segment_size(), 1470); let first_seg = SegmentationInfo::new(false, true, 32, 1024, 0, 8);
1844 assert!(first_seg.is_first_segment());
1845 assert!(first_seg.is_last_segment()); let last_seg = SegmentationInfo::new(false, true, 16, 480, 3, 5);
1849 assert!(!last_seg.is_first_segment());
1850 assert!(last_seg.is_last_segment());
1851 }
1852
1853 #[test]
1854 fn test_segment_reassembly_buffer() {
1855 let mut buffer = SegmentReassemblyBuffer::new(42, 1024);
1856 assert_eq!(buffer.invoke_id, 42);
1857 assert_eq!(buffer.max_apdu_length, 1024);
1858 assert!(!buffer.is_complete());
1859 assert_eq!(buffer.missing_segments(), Vec::<u8>::new());
1860
1861 buffer.add_segment(0, vec![1, 2, 3], false).unwrap();
1863 buffer.add_segment(1, vec![4, 5, 6], false).unwrap();
1864 buffer.add_segment(2, vec![7, 8, 9], true).unwrap(); assert!(buffer.is_complete());
1867 assert_eq!(buffer.total_segments, Some(3));
1868
1869 let reassembled = buffer.reassemble().unwrap();
1871 assert_eq!(reassembled, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
1872
1873 let mut incomplete_buffer = SegmentReassemblyBuffer::new(43, 1024);
1875 incomplete_buffer.add_segment(0, vec![1, 2], false).unwrap();
1876 incomplete_buffer.add_segment(2, vec![5, 6], true).unwrap(); assert!(!incomplete_buffer.is_complete());
1879 assert_eq!(incomplete_buffer.missing_segments(), vec![1]);
1880 }
1881
1882 #[test]
1883 fn test_segmentation_manager() {
1884 let mut manager = SegmentationManager::new();
1885 assert_eq!(manager.active_reassemblies(), 0);
1886
1887 let large_data = vec![0u8; 100]; let segments = manager.segment_message(&large_data, 30, 10).unwrap();
1890 assert_eq!(segments.len(), 4); assert_eq!(segments[0].len(), 30);
1892 assert_eq!(segments[1].len(), 30);
1893 assert_eq!(segments[2].len(), 30);
1894 assert_eq!(segments[3].len(), 10); let invoke_id = 100;
1898 let max_apdu = 1024;
1899
1900 let result1 = manager
1902 .process_segment(invoke_id, 0, vec![1, 2, 3], true, max_apdu)
1903 .unwrap();
1904 assert!(result1.is_none()); assert_eq!(manager.active_reassemblies(), 1);
1906
1907 let result2 = manager
1909 .process_segment(invoke_id, 1, vec![4, 5, 6], false, max_apdu)
1910 .unwrap();
1911 assert!(result2.is_some()); assert_eq!(result2.unwrap(), vec![1, 2, 3, 4, 5, 6]);
1913 assert_eq!(manager.active_reassemblies(), 0); manager
1917 .process_segment(200, 0, vec![10, 20], true, max_apdu)
1918 .unwrap();
1919 manager
1920 .process_segment(200, 2, vec![50, 60], false, max_apdu)
1921 .unwrap();
1922 let missing = manager.get_missing_segments(200);
1923 assert_eq!(missing, vec![1]);
1924 }
1925
1926 #[test]
1927 fn test_segmentation_error_cases() {
1928 let manager = SegmentationManager::new();
1929
1930 let huge_data = vec![0u8; 1000];
1932 let result = manager.segment_message(&huge_data, 100, 5); assert!(result.is_err());
1934 match result.unwrap_err() {
1935 ApplicationError::SegmentationError(msg) => {
1936 assert!(msg.contains("too large"));
1937 }
1938 _ => panic!("Expected SegmentationError"),
1939 }
1940
1941 let mut buffer = SegmentReassemblyBuffer::new(1, 100);
1943 buffer.add_segment(0, vec![1, 2], false).unwrap();
1944 let result = buffer.reassemble();
1946 assert!(result.is_err());
1947 match result.unwrap_err() {
1948 ApplicationError::SegmentationError(msg) => {
1949 assert!(msg.contains("Incomplete"));
1950 }
1951 _ => panic!("Expected SegmentationError"),
1952 }
1953 }
1954
1955 #[test]
1956 fn test_segmentation_duplicate_handling() {
1957 let mut buffer = SegmentReassemblyBuffer::new(1, 1024);
1958
1959 buffer.add_segment(0, vec![1, 2, 3], false).unwrap();
1961 assert_eq!(buffer.segments.len(), 1);
1962
1963 buffer.add_segment(0, vec![4, 5, 6], false).unwrap();
1965 assert_eq!(buffer.segments.len(), 1);
1966 assert_eq!(buffer.segments[0].1, vec![1, 2, 3]); buffer.add_segment(1, vec![7, 8, 9], true).unwrap();
1970 assert_eq!(buffer.segments.len(), 2);
1971 assert!(buffer.is_complete());
1972
1973 let reassembled = buffer.reassemble().unwrap();
1974 assert_eq!(reassembled, vec![1, 2, 3, 7, 8, 9]);
1975 }
1976}