// Copyright (C) 2018-2019 Robin Krahl // SPDX-License-Identifier: MIT use std::convert; use crate::error::{Error, LibraryError}; /// The configuration for a Nitrokey. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Config { /// If set, the stick will generate a code from the HOTP slot with the given number if Num Lock /// is pressed. The slot number must be 0, 1 or 2. pub num_lock: Option, /// If set, the stick will generate a code from the HOTP slot with the given number if Caps /// Lock is pressed. The slot number must be 0, 1 or 2. pub caps_lock: Option, /// If set, the stick will generate a code from the HOTP slot with the given number if Scroll /// Lock is pressed. The slot number must be 0, 1 or 2. pub scroll_lock: Option, /// If set, OTP generation using [`get_hotp_code`][] or [`get_totp_code`][] requires user /// authentication. Otherwise, OTPs can be generated without authentication. /// /// [`get_hotp_code`]: trait.ProvideOtp.html#method.get_hotp_code /// [`get_totp_code`]: trait.ProvideOtp.html#method.get_totp_code pub user_password: bool, } #[derive(Debug)] pub struct RawConfig { pub num_lock: u8, pub caps_lock: u8, pub scroll_lock: u8, pub user_password: bool, } fn config_otp_slot_to_option(value: u8) -> Option { if value < 3 { Some(value) } else { None } } fn option_to_config_otp_slot(value: Option) -> Result { if let Some(value) = value { if value < 3 { Ok(value) } else { Err(LibraryError::InvalidSlot.into()) } } else { Ok(255) } } impl Config { /// Constructs a new instance of this struct. pub fn new( num_lock: Option, caps_lock: Option, scroll_lock: Option, user_password: bool, ) -> Config { Config { num_lock, caps_lock, scroll_lock, user_password, } } } impl convert::TryFrom for RawConfig { type Error = Error; fn try_from(config: Config) -> Result { Ok(RawConfig { num_lock: option_to_config_otp_slot(config.num_lock)?, caps_lock: option_to_config_otp_slot(config.caps_lock)?, scroll_lock: option_to_config_otp_slot(config.scroll_lock)?, user_password: config.user_password, }) } } impl From<&nitrokey_sys::NK_status> for RawConfig { fn from(status: &nitrokey_sys::NK_status) -> Self { Self { num_lock: status.config_numlock, caps_lock: status.config_capslock, scroll_lock: status.config_scrolllock, user_password: status.otp_user_password, } } } impl Into for RawConfig { fn into(self) -> Config { Config { num_lock: config_otp_slot_to_option(self.num_lock), caps_lock: config_otp_slot_to_option(self.caps_lock), scroll_lock: config_otp_slot_to_option(self.scroll_lock), user_password: self.user_password, } } }