Compare commits
	
		
			5 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0dd05c0d91 | |||
| 78248eb2a5 | |||
| 4d9361e383 | |||
| 85e07886e9 | |||
| ba20f457f8 | 
							
								
								
									
										27
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
{
 | 
			
		||||
  "nodes": {
 | 
			
		||||
    "nixpkgs": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1714906307,
 | 
			
		||||
        "narHash": "sha256-UlRZtrCnhPFSJlDQE7M0eyhgvuuHBTe1eJ9N9AQlJQ0=",
 | 
			
		||||
        "owner": "nixos",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "25865a40d14b3f9cf19f19b924e2ab4069b09588",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nixos",
 | 
			
		||||
        "ref": "nixos-unstable",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "root": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "nixpkgs": "nixpkgs"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "root": "root",
 | 
			
		||||
  "version": 7
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
{
 | 
			
		||||
  description = "Rust setup";
 | 
			
		||||
 | 
			
		||||
  inputs = {
 | 
			
		||||
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  outputs = { self, nixpkgs, ... }:
 | 
			
		||||
    let
 | 
			
		||||
      system = "x86_64-linux";
 | 
			
		||||
      pkgs = nixpkgs.legacyPackages.${system};
 | 
			
		||||
    in {
 | 
			
		||||
      devShells.${system}.default = pkgs.mkShell {
 | 
			
		||||
 | 
			
		||||
        buildInputs = with pkgs; [
 | 
			
		||||
          cargo
 | 
			
		||||
          clippy
 | 
			
		||||
          rustfmt
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/r701.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/r701.rs
									
									
									
									
									
								
							@@ -65,26 +65,28 @@ impl R701 {
 | 
			
		||||
 | 
			
		||||
        // If the response length is right but the header is `01 00 00 00 00 00
 | 
			
		||||
        // 00 00` then the request is been succesful but the name was not found
 | 
			
		||||
        if response[..12] == [0xaa, 0x55, 0x01, 0, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
            && response.len() == 34
 | 
			
		||||
        if response.len() == 34
 | 
			
		||||
            && response[..12] == [0xaa, 0x55, 0x01, 0, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
        {
 | 
			
		||||
            return Ok(None);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If one between the response length or the response header is wrong
 | 
			
		||||
        // return an error
 | 
			
		||||
        if response[..12] != [0xaa, 0x55, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
            || response.len() != 34
 | 
			
		||||
        if response.len() != 34
 | 
			
		||||
            || response[..12] != [0xaa, 0x55, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
        {
 | 
			
		||||
            return Err(Error::new(InvalidData, "Malformed response"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get the name as a UTF-8 string and delete the `\0` at the end
 | 
			
		||||
        Ok(Some(
 | 
			
		||||
            String::from_utf8_lossy(&response[12..22])
 | 
			
		||||
                .trim_end_matches(char::from(0))
 | 
			
		||||
                .to_string(),
 | 
			
		||||
        ))
 | 
			
		||||
        let name = String::from_utf8_lossy(&response[12..22])
 | 
			
		||||
            .trim_end_matches('\0')
 | 
			
		||||
            .to_string();
 | 
			
		||||
 | 
			
		||||
        // Return None if the name is empty, else return the name wrapped into a
 | 
			
		||||
        // Some
 | 
			
		||||
        Ok(Some(name).filter(|name| !name.is_empty()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_total_record_count(&mut self) -> Result<u16> {
 | 
			
		||||
@@ -94,9 +96,9 @@ impl R701 {
 | 
			
		||||
 | 
			
		||||
        // If one between the response length or the response header is wrong
 | 
			
		||||
        // return an error
 | 
			
		||||
        if response[..4] != [0xaa, 0x55, 0x01, 0x01]
 | 
			
		||||
        if response.len() != 10
 | 
			
		||||
            || response[..4] != [0xaa, 0x55, 0x01, 0x01]
 | 
			
		||||
            || response[6..] != [0u8; 4]
 | 
			
		||||
            || response.len() != 10
 | 
			
		||||
        {
 | 
			
		||||
            return Err(Error::new(InvalidData, "Malformed response"));
 | 
			
		||||
        }
 | 
			
		||||
@@ -133,15 +135,15 @@ impl R701 {
 | 
			
		||||
 | 
			
		||||
        // If one between the response length, the response header or the last
 | 
			
		||||
        // two bits is wrong return an error
 | 
			
		||||
        if response[..12] != [0xaa, 0x55, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
        if response.len() != 1038
 | 
			
		||||
            || response[..12] != [0xaa, 0x55, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0x55, 0xaa]
 | 
			
		||||
            || response[1036..] != [0, 0]
 | 
			
		||||
            || response.len() != 1038
 | 
			
		||||
        {
 | 
			
		||||
            return Err(Error::new(InvalidData, "Malformed response"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Return only the payload bits as a vector
 | 
			
		||||
        Ok(response[12..response.len() - 2].to_vec())
 | 
			
		||||
        Ok(response[12..1036].to_vec())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn iter(&mut self) -> Result<RecordIterator> {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,25 +6,36 @@ pub struct RecordIterator<'a> {
 | 
			
		||||
    r701: &'a mut R701,
 | 
			
		||||
    input_buffer: Vec<u8>,
 | 
			
		||||
    sequence_number: u16,
 | 
			
		||||
    record_count: u16,
 | 
			
		||||
    total_records: u16,
 | 
			
		||||
    record_count: u16,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> RecordIterator<'a> {
 | 
			
		||||
    pub fn from(r701: &'a mut R701) -> Result<Self> {
 | 
			
		||||
        // Ping the endpoint
 | 
			
		||||
        r701.ping()?;
 | 
			
		||||
 | 
			
		||||
        // Get the total number of records
 | 
			
		||||
        let total_records = r701.get_total_record_count()?;
 | 
			
		||||
 | 
			
		||||
        // Calculate the sequence number on which the last record resides and
 | 
			
		||||
        // the index of the first `ff` byte, avoiding overflows
 | 
			
		||||
        let sequence_number = (total_records as u32 * 12 / 1024) as u16;
 | 
			
		||||
        let first_useless_byte_index = total_records as usize * 12 % 1024;
 | 
			
		||||
 | 
			
		||||
        // The endpoint expects the first block of records to be sent first
 | 
			
		||||
        r701.get_record_bytes(total_records, 0)?;
 | 
			
		||||
 | 
			
		||||
        // Get the last records and cut out all the trailing `ff` bytes
 | 
			
		||||
        let input_buffer = r701
 | 
			
		||||
            .get_record_bytes(total_records, sequence_number)?
 | 
			
		||||
            .drain(..first_useless_byte_index)
 | 
			
		||||
            .collect::<Vec<u8>>();
 | 
			
		||||
 | 
			
		||||
        // Return a new Iterator
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            r701,
 | 
			
		||||
            input_buffer: Vec::new(),
 | 
			
		||||
            record_count: 0,
 | 
			
		||||
            sequence_number: 0,
 | 
			
		||||
            input_buffer,
 | 
			
		||||
            sequence_number,
 | 
			
		||||
            total_records,
 | 
			
		||||
            record_count: total_records,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -33,32 +44,39 @@ impl<'a> Iterator for RecordIterator<'a> {
 | 
			
		||||
    type Item = Record;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        self.record_count += 1;
 | 
			
		||||
 | 
			
		||||
        // If we exceeded the total number of records, return None
 | 
			
		||||
        if self.record_count > self.total_records {
 | 
			
		||||
        // Stop iterating when there are no more records
 | 
			
		||||
        if self.record_count == 0 {
 | 
			
		||||
            return None;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If the buffer is empty, make another request to the endpoint asking
 | 
			
		||||
        // for more data
 | 
			
		||||
        self.record_count -= 1;
 | 
			
		||||
 | 
			
		||||
        // If the input buffer is almost empty, make another request to the
 | 
			
		||||
        // endpoint asking for more data
 | 
			
		||||
        if self.input_buffer.len() < 12 {
 | 
			
		||||
            let bytes = &mut self
 | 
			
		||||
            // If the buffer is almost empty but the sequence number is already
 | 
			
		||||
            // zero, stop iterating
 | 
			
		||||
            if self.sequence_number == 0 {
 | 
			
		||||
                return None;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.sequence_number -= 1;
 | 
			
		||||
 | 
			
		||||
            // Request new bytes
 | 
			
		||||
            let bytes = self
 | 
			
		||||
                .r701
 | 
			
		||||
                .get_record_bytes(self.total_records, self.sequence_number)
 | 
			
		||||
                .ok()?;
 | 
			
		||||
 | 
			
		||||
            self.input_buffer.append(bytes);
 | 
			
		||||
            self.sequence_number += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If the record bytes are set to `ff ff ff ff ff ff ff ff ff ff ff ff`,
 | 
			
		||||
        // return None
 | 
			
		||||
        if self.input_buffer[..12] == [0xff_u8; 12] {
 | 
			
		||||
            return None;
 | 
			
		||||
            // Put the bytes at the start of the vector
 | 
			
		||||
            self.input_buffer.splice(0..0, bytes.iter().copied());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Return a new Record
 | 
			
		||||
        self.input_buffer.drain(..12).as_slice().try_into().ok()
 | 
			
		||||
        self.input_buffer
 | 
			
		||||
            .drain(self.input_buffer.len() - 12..)
 | 
			
		||||
            .as_slice()
 | 
			
		||||
            .try_into()
 | 
			
		||||
            .ok()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user