blob: 589dfc3143be3f0e3d8097c82da6ec81c5ad65b2 [file] [log] [blame]
Philipp Vollmer090398c2018-06-29 15:14:54 +02001pub mod gap_types {
2 pub static COMPLETE_LOCAL_NAME: u8 = 0x09;
3 pub static SERVICE_DATA: u8 = 0x16;
4 pub static UUID: u8 = 0x02;
5 pub static FLAGS: u8 = 0x01;
6}
7
8pub mod flags {
9 pub static LE_GENERAL_DISCOVERABLE: u8 = 0x01;
10}
11
12pub struct BlePayload {
torfmaster906d2972019-02-15 23:38:23 +010013 bytes: [u8; 39],
14 occupied: usize,
Philipp Vollmer090398c2018-06-29 15:14:54 +020015}
16
17impl BlePayload {
torfmaster906d2972019-02-15 23:38:23 +010018 pub fn add(&mut self, kind: u8, content: &[u8]) -> Result<(), ()> {
19 self.check_can_write_num_bytes(content.len() + 2)?;
20
21 self.bytes[self.occupied] = (content.len() + 1) as u8;
22 self.bytes[self.occupied + 1] = kind;
23 let write = &mut self.bytes[self.occupied + 2..(self.occupied + content.len() + 2)];
JOE1994d1ec41e2020-07-02 18:37:36 -040024 write.copy_from_slice(content);
torfmaster906d2972019-02-15 23:38:23 +010025 self.occupied += 2 + content.len();
26 Ok(())
Philipp Vollmer090398c2018-06-29 15:14:54 +020027 }
28
torfmaster906d2972019-02-15 23:38:23 +010029 pub fn add_flag(&mut self, flag: u8) -> Result<(), ()> {
30 self.check_can_write_num_bytes(3)?;
31
32 self.bytes[self.occupied] = 2;
33 self.bytes[self.occupied + 1] = gap_types::FLAGS;
34 self.bytes[self.occupied + 2] = flag;
35 self.occupied += 3;
36 Ok(())
Philipp Vollmer090398c2018-06-29 15:14:54 +020037 }
38
torfmaster906d2972019-02-15 23:38:23 +010039 pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) -> Result<(), ()> {
40 self.check_can_write_num_bytes(4 + content.len())?;
41 self.bytes[self.occupied] = (content.len() + 3) as u8;
42 self.bytes[self.occupied + 1] = gap_types::SERVICE_DATA;
43 self.bytes[self.occupied + 2] = uuid[0];
44 self.bytes[self.occupied + 3] = uuid[1];
45
46 let write = &mut self.bytes[self.occupied + 4..(self.occupied + content.len() + 4)];
JOE1994d1ec41e2020-07-02 18:37:36 -040047 write.copy_from_slice(content);
torfmaster906d2972019-02-15 23:38:23 +010048 self.occupied += 4 + content.len();
49 Ok(())
50 }
51
52 fn check_can_write_num_bytes(&self, number: usize) -> Result<(), ()> {
53 if self.occupied + number <= self.bytes.len() {
54 Ok(())
55 } else {
56 Err(())
Philipp Vollmer090398c2018-06-29 15:14:54 +020057 }
58 }
59}
60
torfmastere6c4ecb2020-01-04 20:34:33 +010061impl Default for BlePayload {
62 fn default() -> Self {
63 BlePayload {
64 bytes: [0; 39],
65 occupied: 0,
66 }
67 }
68}
torfmaster906d2972019-02-15 23:38:23 +010069impl AsRef<[u8]> for BlePayload {
70 fn as_ref(&self) -> &[u8] {
71 &self.bytes[0..self.occupied]
72 }
73}
74
Philipp Vollmer090398c2018-06-29 15:14:54 +020075#[cfg(test)]
76mod test {
Woyten012fe572018-08-24 21:46:51 +020077 use super::*;
78
Philipp Vollmer090398c2018-06-29 15:14:54 +020079 #[test]
torfmaster906d2972019-02-15 23:38:23 +010080 fn test_add() {
torfmastere6c4ecb2020-01-04 20:34:33 +010081 let mut pld = BlePayload::default();
Woyten8bedbd72019-12-17 17:08:29 +010082 pld.add(1, &[2]).unwrap();
torfmaster906d2972019-02-15 23:38:23 +010083 assert_eq!(pld.as_ref().len(), 3);
84 assert_eq!(pld.as_ref(), &mut [2, 1, 2])
Philipp Vollmer090398c2018-06-29 15:14:54 +020085 }
86
87 #[test]
torfmaster906d2972019-02-15 23:38:23 +010088 fn test_add_service_payload() {
torfmastere6c4ecb2020-01-04 20:34:33 +010089 let mut pld = BlePayload::default();
Woyten8bedbd72019-12-17 17:08:29 +010090 pld.add_service_payload([1, 2], &[2]).unwrap();
torfmaster906d2972019-02-15 23:38:23 +010091 assert_eq!(pld.as_ref(), &[4, 0x16, 1, 2, 2])
92 }
93
94 #[test]
95 fn test_add_service_payload_two_times() {
torfmastere6c4ecb2020-01-04 20:34:33 +010096 let mut pld = BlePayload::default();
Woyten8bedbd72019-12-17 17:08:29 +010097 pld.add_service_payload([1, 2], &[2]).unwrap();
98 pld.add_service_payload([1, 2], &[2, 3]).unwrap();
torfmaster906d2972019-02-15 23:38:23 +010099
100 assert_eq!(pld.as_ref(), &[4, 0x16, 1, 2, 2, 5, 0x16, 1, 2, 2, 3])
101 }
102
103 #[test]
104 fn big_data_causes_error() {
torfmastere6c4ecb2020-01-04 20:34:33 +0100105 let mut pld = BlePayload::default();
torfmaster906d2972019-02-15 23:38:23 +0100106 assert!(pld.add_service_payload([1, 2], &[0; 36]).is_err());
107 }
108
109 #[test]
110 fn initial_size_is_zero() {
torfmastere6c4ecb2020-01-04 20:34:33 +0100111 let pld = BlePayload::default();
torfmaster906d2972019-02-15 23:38:23 +0100112 assert_eq!(pld.as_ref().len(), 0);
Philipp Vollmer090398c2018-06-29 15:14:54 +0200113 }
114}