Skip to main content

osdp/reply/
bio.rs

1//! `osdp_BIOREADR` (`0x57`) and `osdp_BIOMATCHR` (`0x58`).
2//!
3//! # Spec: §7.14, §7.15
4
5use crate::command::{BioFormat, BioType};
6use crate::error::Error;
7use alloc::vec::Vec;
8
9/// `osdp_BIOREADR` body.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct BioReadR {
12    /// Reader number.
13    pub reader: u8,
14    /// Biometric type captured.
15    pub bio_type: BioType,
16    /// Biometric format used.
17    pub bio_format: BioFormat,
18    /// Quality score (0..100) of the captured sample.
19    pub quality: u8,
20    /// Captured biometric data (template or raw).
21    pub data: Vec<u8>,
22}
23
24impl BioReadR {
25    /// Encode.
26    pub fn encode(&self) -> Result<Vec<u8>, Error> {
27        if self.data.len() > u16::MAX as usize {
28            return Err(Error::MalformedPayload {
29                code: 0x57,
30                reason: "BIOREADR data > 65535 bytes",
31            });
32        }
33        let mut out = Vec::with_capacity(6 + self.data.len());
34        out.push(self.reader);
35        out.push(self.bio_type.as_byte());
36        out.push(self.bio_format.as_byte());
37        out.push(self.quality);
38        out.extend_from_slice(&(self.data.len() as u16).to_le_bytes());
39        out.extend_from_slice(&self.data);
40        Ok(out)
41    }
42
43    /// Decode.
44    pub fn decode(data: &[u8]) -> Result<Self, Error> {
45        if data.len() < 6 {
46            return Err(Error::MalformedPayload {
47                code: 0x57,
48                reason: "BIOREADR requires at least 6 bytes",
49            });
50        }
51        let length = u16::from_le_bytes([data[4], data[5]]) as usize;
52        if data.len() != 6 + length {
53            return Err(Error::MalformedPayload {
54                code: 0x57,
55                reason: "BIOREADR length disagrees with payload",
56            });
57        }
58        Ok(Self {
59            reader: data[0],
60            bio_type: BioType::from_byte(data[1]),
61            bio_format: BioFormat::from_byte(data[2]),
62            quality: data[3],
63            data: data[6..6 + length].to_vec(),
64        })
65    }
66}
67
68/// `osdp_BIOMATCHR` body.
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub struct BioMatchR {
71    /// Reader number.
72    pub reader: u8,
73    /// Match outcome (`0` = no match, `1` = match).
74    pub result: u8,
75    /// Score (0..100).
76    pub score: u8,
77}
78
79impl BioMatchR {
80    /// Encode.
81    pub fn encode(&self) -> Result<Vec<u8>, Error> {
82        Ok(alloc::vec![self.reader, self.result, self.score])
83    }
84
85    /// Decode.
86    pub fn decode(data: &[u8]) -> Result<Self, Error> {
87        if data.len() != 3 {
88            return Err(Error::MalformedPayload {
89                code: 0x58,
90                reason: "BIOMATCHR requires 3 bytes",
91            });
92        }
93        Ok(Self {
94            reader: data[0],
95            result: data[1],
96            score: data[2],
97        })
98    }
99}