rustbac_core/services/
i_am.rs1use crate::apdu::UnconfirmedRequestHeader;
2use crate::encoding::{
3 primitives::{
4 decode_app_enumerated, decode_app_unsigned, encode_app_enumerated, encode_app_unsigned,
5 },
6 reader::Reader,
7 tag::{AppTag, Tag},
8 writer::Writer,
9};
10use crate::types::ObjectId;
11use crate::{DecodeError, EncodeError};
12
13pub const SERVICE_I_AM: u8 = 0x00;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct IAmRequest {
17 pub device_id: ObjectId,
18 pub max_apdu: u32,
19 pub segmentation: u32,
20 pub vendor_id: u32,
21}
22
23impl IAmRequest {
24 pub fn encode(&self, w: &mut Writer<'_>) -> Result<(), EncodeError> {
25 UnconfirmedRequestHeader {
26 service_choice: SERVICE_I_AM,
27 }
28 .encode(w)?;
29
30 Tag::Application {
31 tag: AppTag::ObjectId,
32 len: 4,
33 }
34 .encode(w)?;
35 w.write_all(&self.device_id.raw().to_be_bytes())?;
36 encode_app_unsigned(w, self.max_apdu)?;
37 encode_app_enumerated(w, self.segmentation)?;
38 encode_app_unsigned(w, self.vendor_id)?;
39 Ok(())
40 }
41
42 pub fn decode_after_header(r: &mut Reader<'_>) -> Result<Self, DecodeError> {
43 let device_id = match Tag::decode(r)? {
44 Tag::Application {
45 tag: AppTag::ObjectId,
46 len: 4,
47 } => {
48 let b = r.read_exact(4)?;
49 ObjectId::from_raw(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
50 }
51 _ => return Err(DecodeError::InvalidTag),
52 };
53 let max_apdu = decode_app_unsigned(r)?;
54 let segmentation = decode_app_enumerated(r)?;
55 let vendor_id = decode_app_unsigned(r)?;
56
57 Ok(Self {
58 device_id,
59 max_apdu,
60 segmentation,
61 vendor_id,
62 })
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::IAmRequest;
69 use crate::apdu::UnconfirmedRequestHeader;
70 use crate::encoding::{reader::Reader, tag::AppTag, tag::Tag, writer::Writer};
71 use crate::types::{ObjectId, ObjectType};
72
73 #[test]
74 fn i_am_segmentation_is_enumerated() {
75 let req = IAmRequest {
76 device_id: ObjectId::new(ObjectType::Device, 1234),
77 max_apdu: 1476,
78 segmentation: 3,
79 vendor_id: 260,
80 };
81 let mut buf = [0u8; 64];
82 let mut w = Writer::new(&mut buf);
83 req.encode(&mut w).unwrap();
84
85 let mut r = Reader::new(w.as_written());
86 let _hdr = UnconfirmedRequestHeader::decode(&mut r).unwrap();
87 let _obj = Tag::decode(&mut r).unwrap();
88 let _obj_data = r.read_exact(4).unwrap();
89 let _max = Tag::decode(&mut r).unwrap();
90 let _max_data = r.read_exact(2).unwrap();
91 let seg_tag = Tag::decode(&mut r).unwrap();
92 assert_eq!(
93 seg_tag,
94 Tag::Application {
95 tag: AppTag::Enumerated,
96 len: 1
97 }
98 );
99 }
100}