use std::str::FromStr;
use adapter::{AdapterError, AdapterErrorKind::ResponseError};
use serial_number::SerialNumber;
pub(super) const CONNECTOR_STATUS_OK: &str = "OK";
#[derive(Clone, Debug)]
pub struct ConnectorStatus {
pub message: String,
pub serial_number: Option<SerialNumber>,
pub version: String,
pub pid: u32,
}
impl ConnectorStatus {
pub fn parse(response_body: &str) -> Result<Self, AdapterError> {
let mut response_message: Option<&str> = None;
let mut response_serial: Option<&str> = None;
let mut response_version: Option<&str> = None;
let mut response_pid: Option<&str> = None;
for line in response_body.split('\n') {
if line.is_empty() {
continue;
}
let mut fields = line.split('=');
let key = fields
.next()
.ok_or_else(|| err!(ResponseError, "couldn't parse key"))?;
let value = fields
.next()
.ok_or_else(|| err!(ResponseError, "couldn't parse value"))?;
if let Some(remaining) = fields.next() {
fail!(ResponseError, "unexpected additional data: {}", remaining)
}
match key {
"status" => response_message = Some(value),
"serial" => response_serial = Some(value),
"version" => response_version = Some(value),
"pid" => response_pid = Some(value),
_ => (),
}
}
let message = response_message
.ok_or_else(|| err!(ResponseError, "missing status"))?
.to_owned();
let serial_number = match response_serial {
Some("*") => None,
Some(s) => Some(SerialNumber::from_str(s)?),
None => fail!(ResponseError, "missing serial"),
};
let version = response_version
.ok_or_else(|| err!(ResponseError, "missing version"))?
.to_owned();
let pid = response_pid
.ok_or_else(|| err!(ResponseError, "missing PID"))?
.parse()
.map_err(|_| err!(ResponseError, "invalid PID: {}", response_pid.unwrap()))?;
Ok(Self {
message,
serial_number,
version,
pid,
})
}
pub fn is_ok(&self) -> bool {
if self.message == CONNECTOR_STATUS_OK {
true
} else {
debug!(
"bad status message from yubihsm-connector: {}",
&self.message
);
false
}
}
}