#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::unwrap_used))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::expect_used))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::panic))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::todo))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::unreachable))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::indexing_slicing))]
#![cfg_attr(not(any(test, feature = "virt")), deny(clippy::unwrap_in_result))]
#[cfg(all(
feature = "nfc",
not(any(feature = "nfc-backend-pcsc", feature = "nfc-backend-libnfc"))
))]
compile_error!(
"the `nfc` feature is an umbrella that requires at least one backend; enable `nfc-backend-pcsc` and/or `nfc-backend-libnfc`"
);
pub mod fido;
pub mod management;
pub mod ops;
pub mod pin;
pub mod proto;
pub mod transport;
pub mod u2f;
pub mod webauthn;
use std::sync::Arc;
use tokio::sync::oneshot;
#[macro_use]
extern crate num_derive;
#[macro_use]
extern crate bitflags;
macro_rules! unwrap_field {
($field:expr) => {{
if let Some(f) = $field {
f
} else {
tracing::error!(
"Device response did not contain expected field: {}",
stringify!($field)
);
return Err(Error::Platform(PlatformError::InvalidDeviceResponse));
}
}};
}
use pin::{PinNotSetReason, PinRequestReason};
pub(crate) use unwrap_field;
#[derive(Debug)]
pub enum Transport {
Usb,
Ble,
}
#[derive(Debug, Clone)]
#[cfg_attr(any(test, feature = "virt"), derive(PartialEq))]
pub enum UvUpdate {
UvRetry {
attempts_left: Option<u32>,
},
PinRequired(PinRequiredUpdate),
PresenceRequired,
PinNotSet(PinNotSetUpdate),
}
#[derive(Debug, Clone)]
pub struct PinRequiredUpdate {
reply_to: Arc<oneshot::Sender<String>>,
pub reason: PinRequestReason,
pub attempts_left: Option<u32>,
}
impl PinRequiredUpdate {
pub fn send_pin(self, pin: &str) -> Result<(), String> {
match Arc::into_inner(self.reply_to) {
Some(sender) => sender
.send(pin.to_string())
.map_err(|_| "Failed to send PIN".to_string()),
None => Err("Multiple references to reply_to exist; cannot send PIN".to_string()),
}
}
pub fn cancel(self) {
drop(self.reply_to)
}
}
#[derive(Debug, Clone)]
pub struct PinNotSetUpdate {
reply_to: Arc<oneshot::Sender<String>>,
pub reason: PinNotSetReason,
}
impl PinNotSetUpdate {
pub fn set_pin(self, pin: &str) -> Result<(), String> {
match Arc::into_inner(self.reply_to) {
Some(sender) => sender
.send(pin.to_string())
.map_err(|_| "Failed to send PIN".to_string()),
None => Err("Multiple references to reply_to exist; cannot send PIN".to_string()),
}
}
pub fn cancel(self) {
drop(self.reply_to)
}
}
#[cfg(any(test, feature = "virt"))]
impl PartialEq for PinRequiredUpdate {
fn eq(&self, other: &Self) -> bool {
self.reason == other.reason && self.attempts_left == other.attempts_left
}
}
#[cfg(any(test, feature = "virt"))]
impl PartialEq for PinNotSetUpdate {
fn eq(&self, other: &Self) -> bool {
self.reason == other.reason
}
}
pub fn available_transports() -> Vec<Transport> {
vec![Transport::Usb, Transport::Ble]
}