library

Online co-op book organization video game
git clone https://git.bradleygannon.com/library.git
Log | Files | Refs

codec.rs (1742B)


      1 #[derive(Default, Debug)]
      2 enum State {
      3     #[default]
      4     Start,
      5     Data(u8),
      6     Escape,
      7     End,
      8 }
      9 
     10 impl State {
     11     const DELIMITER: u8 = 0xff;
     12     const ESCAPE: u8 = 0xfe;
     13     fn next(&mut self, input: u8) {
     14         *self = match (input, &self) {
     15             (Self::DELIMITER, State::Data(_) | State::Start | State::End) => State::End,
     16             (Self::ESCAPE, State::Data(_) | State::Start | State::End) => State::Escape,
     17             (d, _) => State::Data(d),
     18         };
     19     }
     20 }
     21 
     22 #[derive(Default, Debug)]
     23 pub struct Codec {
     24     state: State,
     25     message: Vec<u8>,
     26 }
     27 
     28 impl Codec {
     29     fn next(&mut self, input: u8) -> Option<Vec<u8>> {
     30         self.state.next(input);
     31         match self.state {
     32             State::Data(d) => {
     33                 self.message.push(d);
     34                 None
     35             }
     36             State::End => {
     37                 let complete = self.message.clone();
     38                 self.message.clear();
     39                 Some(complete)
     40             }
     41             State::Start | State::Escape => None,
     42         }
     43     }
     44     pub fn decode(&mut self, input: &[u8]) -> Vec<Vec<u8>> {
     45         let mut output = vec![];
     46         for byte in input {
     47             if let Some(message) = self.next(*byte) {
     48                 output.push(message);
     49             }
     50         }
     51         output
     52     }
     53     pub fn encode(input: &[u8]) -> Vec<u8> {
     54         let mut output = vec![];
     55         for byte in input {
     56             match *byte {
     57                 State::DELIMITER => output.extend_from_slice(&[State::ESCAPE, State::DELIMITER]),
     58                 State::ESCAPE => output.extend_from_slice(&[State::ESCAPE, State::ESCAPE]),
     59                 b => output.push(b),
     60             }
     61         }
     62         output.push(State::DELIMITER);
     63         output
     64     }
     65 }