use async_trait::async_trait;
use crate::Device;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum IoCapability {
DisplayOnly,
DisplayYesNo,
KeyboardOnly,
NoInputNoOutput,
KeyboardDisplay,
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct PairingRejected;
impl std::fmt::Display for PairingRejected {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("pairing rejected")
}
}
impl std::error::Error for PairingRejected {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InvalidPasskey(());
impl std::fmt::Display for InvalidPasskey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("invalid passkey")
}
}
impl std::error::Error for InvalidPasskey {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Passkey(u32);
impl Passkey {
pub fn new(n: u32) -> Self {
assert!(n <= 999_999);
Passkey(n)
}
}
impl std::fmt::Display for Passkey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:06}", self.0)
}
}
impl From<Passkey> for u32 {
fn from(val: Passkey) -> Self {
val.0
}
}
impl std::convert::TryFrom<u32> for Passkey {
type Error = InvalidPasskey;
fn try_from(value: u32) -> Result<Self, Self::Error> {
if value <= 999_999 {
Ok(Passkey(value))
} else {
Err(InvalidPasskey(()))
}
}
}
impl std::str::FromStr for Passkey {
type Err = InvalidPasskey;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<u32>()
.map_err(|_| InvalidPasskey(()))
.and_then(Passkey::try_from)
}
}
#[async_trait]
pub trait PairingAgent: Send + Sync {
fn io_capability(&self) -> IoCapability;
async fn confirm(&self, _device: &Device) -> Result<(), PairingRejected> {
Err(PairingRejected)
}
async fn confirm_passkey(&self, _device: &Device, _passkey: Passkey) -> Result<(), PairingRejected> {
Err(PairingRejected)
}
async fn request_passkey(&self, _device: &Device) -> Result<Passkey, PairingRejected> {
Err(PairingRejected)
}
fn display_passkey(&self, _device: &Device, _passkey: Passkey) {}
}
pub struct NoInputOutputPairingAgent;
#[async_trait]
impl PairingAgent for NoInputOutputPairingAgent {
fn io_capability(&self) -> IoCapability {
IoCapability::NoInputNoOutput
}
async fn confirm(&self, _device: &Device) -> Result<(), PairingRejected> {
Ok(())
}
}