lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

cbor.rs (7987B)


      1 use crate::{
      2     RADROOTS_MESH_FRAME_VERSION, RadrootsMeshError, RadrootsMeshFrame, RadrootsMeshFrameType,
      3     RadrootsMeshPayload, RadrootsMeshScope,
      4 };
      5 use alloc::string::String;
      6 use alloc::vec::Vec;
      7 
      8 pub fn encode_mesh_frame_cbor(frame: &RadrootsMeshFrame) -> Result<Vec<u8>, RadrootsMeshError> {
      9     frame.validate()?;
     10     let mut output = Vec::new();
     11     encode_map_len(&mut output, 7);
     12     encode_uint(&mut output, 0);
     13     encode_uint(&mut output, u64::from(frame.version));
     14     encode_uint(&mut output, 1);
     15     encode_uint(&mut output, frame.frame_type.code());
     16     encode_uint(&mut output, 2);
     17     encode_text(&mut output, &frame.scope_id.cbor_label())?;
     18     encode_uint(&mut output, 3);
     19     encode_text(&mut output, &frame.message_id)?;
     20     encode_uint(&mut output, 4);
     21     encode_uint(&mut output, frame.created_at_ms);
     22     encode_uint(&mut output, 5);
     23     encode_uint(&mut output, frame.ttl);
     24     encode_uint(&mut output, 6);
     25     encode_payload(&mut output, &frame.payload)?;
     26     Ok(output)
     27 }
     28 
     29 pub fn decode_mesh_frame_cbor(bytes: &[u8]) -> Result<RadrootsMeshFrame, RadrootsMeshError> {
     30     let mut cursor = Cursor::new(bytes);
     31     cursor.expect_map_len(7)?;
     32     cursor.expect_uint(0)?;
     33     let version = cursor.read_uint_u16()?;
     34     if version != RADROOTS_MESH_FRAME_VERSION {
     35         return Err(RadrootsMeshError::UnsupportedVersion);
     36     }
     37     cursor.expect_uint(1)?;
     38     let frame_type = RadrootsMeshFrameType::parse_code(cursor.read_uint()?)?;
     39     cursor.expect_uint(2)?;
     40     let scope_id = RadrootsMeshScope::parse(&cursor.read_text()?)?;
     41     cursor.expect_uint(3)?;
     42     let message_id = cursor.read_text()?;
     43     cursor.expect_uint(4)?;
     44     let created_at_ms = cursor.read_uint()?;
     45     cursor.expect_uint(5)?;
     46     let ttl = cursor.read_uint()?;
     47     cursor.expect_uint(6)?;
     48     let payload = cursor.read_payload()?;
     49     cursor.finish()?;
     50     let frame = RadrootsMeshFrame {
     51         version,
     52         frame_type,
     53         scope_id,
     54         message_id,
     55         created_at_ms,
     56         ttl,
     57         payload,
     58     };
     59     frame.validate()?;
     60     Ok(frame)
     61 }
     62 
     63 fn encode_payload(
     64     output: &mut Vec<u8>,
     65     payload: &RadrootsMeshPayload,
     66 ) -> Result<(), RadrootsMeshError> {
     67     payload.validate()?;
     68     encode_map_len(output, 0);
     69     Ok(())
     70 }
     71 
     72 fn encode_uint(output: &mut Vec<u8>, value: u64) {
     73     encode_major(output, 0, value);
     74 }
     75 
     76 fn encode_text(output: &mut Vec<u8>, value: &str) -> Result<(), RadrootsMeshError> {
     77     let len = u64::try_from(value.len()).map_err(|_| RadrootsMeshError::InvalidCbor)?;
     78     encode_major(output, 3, len);
     79     output.extend_from_slice(value.as_bytes());
     80     Ok(())
     81 }
     82 
     83 fn encode_map_len(output: &mut Vec<u8>, len: u64) {
     84     encode_major(output, 5, len);
     85 }
     86 
     87 fn encode_major(output: &mut Vec<u8>, major: u8, value: u64) {
     88     let prefix = major << 5;
     89     match value {
     90         0..=23 => output.push(prefix | value as u8),
     91         24..=0xff => output.extend_from_slice(&[prefix | 24, value as u8]),
     92         0x100..=0xffff => {
     93             output.push(prefix | 25);
     94             output.extend_from_slice(&(value as u16).to_be_bytes());
     95         }
     96         0x1_0000..=0xffff_ffff => {
     97             output.push(prefix | 26);
     98             output.extend_from_slice(&(value as u32).to_be_bytes());
     99         }
    100         _ => {
    101             output.push(prefix | 27);
    102             output.extend_from_slice(&value.to_be_bytes());
    103         }
    104     }
    105 }
    106 
    107 struct Cursor<'a> {
    108     bytes: &'a [u8],
    109     offset: usize,
    110 }
    111 
    112 impl<'a> Cursor<'a> {
    113     fn new(bytes: &'a [u8]) -> Self {
    114         Self { bytes, offset: 0 }
    115     }
    116 
    117     fn read_byte(&mut self) -> Result<u8, RadrootsMeshError> {
    118         let byte = self
    119             .bytes
    120             .get(self.offset)
    121             .copied()
    122             .ok_or(RadrootsMeshError::InvalidCbor)?;
    123         self.offset += 1;
    124         Ok(byte)
    125     }
    126 
    127     fn read_exact(&mut self, len: usize) -> Result<&'a [u8], RadrootsMeshError> {
    128         let end = self
    129             .offset
    130             .checked_add(len)
    131             .ok_or(RadrootsMeshError::InvalidCbor)?;
    132         let slice = self
    133             .bytes
    134             .get(self.offset..end)
    135             .ok_or(RadrootsMeshError::InvalidCbor)?;
    136         self.offset = end;
    137         Ok(slice)
    138     }
    139 
    140     fn read_major(&mut self, expected_major: u8) -> Result<u64, RadrootsMeshError> {
    141         let initial = self.read_byte()?;
    142         if initial >> 5 != expected_major {
    143             return Err(RadrootsMeshError::InvalidCbor);
    144         }
    145         match initial & 0x1f {
    146             value @ 0..=23 => Ok(u64::from(value)),
    147             24 => {
    148                 let value = u64::from(self.read_byte()?);
    149                 if value < 24 {
    150                     return Err(RadrootsMeshError::InvalidCbor);
    151                 }
    152                 Ok(value)
    153             }
    154             25 => {
    155                 let bytes = self.read_exact(2)?;
    156                 let value = u64::from(u16::from_be_bytes([bytes[0], bytes[1]]));
    157                 if value < 0x100 {
    158                     return Err(RadrootsMeshError::InvalidCbor);
    159                 }
    160                 Ok(value)
    161             }
    162             26 => {
    163                 let bytes = self.read_exact(4)?;
    164                 let value = u64::from(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]));
    165                 if value < 0x1_0000 {
    166                     return Err(RadrootsMeshError::InvalidCbor);
    167                 }
    168                 Ok(value)
    169             }
    170             27 => {
    171                 let bytes = self.read_exact(8)?;
    172                 let value = u64::from_be_bytes([
    173                     bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
    174                 ]);
    175                 if value < 0x1_0000_0000 {
    176                     return Err(RadrootsMeshError::InvalidCbor);
    177                 }
    178                 Ok(value)
    179             }
    180             _ => Err(RadrootsMeshError::InvalidCbor),
    181         }
    182     }
    183 
    184     fn read_uint(&mut self) -> Result<u64, RadrootsMeshError> {
    185         self.read_major(0)
    186     }
    187 
    188     fn read_uint_u16(&mut self) -> Result<u16, RadrootsMeshError> {
    189         u16::try_from(self.read_uint()?).map_err(|_| RadrootsMeshError::InvalidCbor)
    190     }
    191 
    192     fn expect_uint(&mut self, expected: u64) -> Result<(), RadrootsMeshError> {
    193         if self.read_uint()? == expected {
    194             Ok(())
    195         } else {
    196             Err(RadrootsMeshError::InvalidCbor)
    197         }
    198     }
    199 
    200     fn read_text(&mut self) -> Result<String, RadrootsMeshError> {
    201         let len =
    202             usize::try_from(self.read_major(3)?).map_err(|_| RadrootsMeshError::InvalidCbor)?;
    203         let bytes = self.read_exact(len)?;
    204         String::from_utf8(bytes.to_vec()).map_err(|_| RadrootsMeshError::InvalidUtf8)
    205     }
    206 
    207     fn skip_bytes(&mut self) -> Result<(), RadrootsMeshError> {
    208         let len =
    209             usize::try_from(self.read_major(2)?).map_err(|_| RadrootsMeshError::InvalidCbor)?;
    210         self.read_exact(len)?;
    211         Ok(())
    212     }
    213 
    214     fn read_payload(&mut self) -> Result<RadrootsMeshPayload, RadrootsMeshError> {
    215         let initial = self.read_byte()?;
    216         match initial >> 5 {
    217             2 => {
    218                 self.offset -= 1;
    219                 self.skip_bytes()?;
    220                 Err(RadrootsMeshError::PayloadTransmissionForbidden)
    221             }
    222             5 => {
    223                 self.offset -= 1;
    224                 if self.read_major(5)? == 0 {
    225                     Ok(RadrootsMeshPayload::EmptyMap)
    226                 } else {
    227                     Err(RadrootsMeshError::PayloadTransmissionForbidden)
    228                 }
    229             }
    230             _ => Err(RadrootsMeshError::InvalidCbor),
    231         }
    232     }
    233 
    234     fn expect_map_len(&mut self, expected: u64) -> Result<(), RadrootsMeshError> {
    235         if self.read_major(5)? == expected {
    236             Ok(())
    237         } else {
    238             Err(RadrootsMeshError::InvalidCbor)
    239         }
    240     }
    241 
    242     fn finish(&self) -> Result<(), RadrootsMeshError> {
    243         if self.offset == self.bytes.len() {
    244             Ok(())
    245         } else {
    246             Err(RadrootsMeshError::InvalidCbor)
    247         }
    248     }
    249 }