use log::trace;
use secrecy::SecretString;
use thiserror::Error;
use crate::{entry::KeyringEntry, io::KeyringIo};
#[derive(Clone, Debug, Error)]
pub enum ReadSecretError {
#[error("Invalid argument: expected {0}, got {1:?}")]
InvalidArgument(&'static str, KeyringIo),
#[error("Entry not ready")]
NotReady,
}
#[derive(Clone, Debug)]
pub enum ReadSecretResult {
Ok(SecretString),
Io(KeyringIo),
Err(ReadSecretError),
}
#[derive(Clone, Debug)]
pub struct ReadSecret {
entry: Option<KeyringEntry>,
}
impl ReadSecret {
pub fn new(entry: KeyringEntry) -> Self {
Self { entry: Some(entry) }
}
pub fn resume(&mut self, arg: Option<KeyringIo>) -> ReadSecretResult {
let Some(arg) = arg else {
let Some(entry) = self.entry.take() else {
return ReadSecretResult::Err(ReadSecretError::NotReady);
};
trace!("need I/O to read secret from keyring entry");
return ReadSecretResult::Io(KeyringIo::Read(Err(entry)));
};
let KeyringIo::Read(io) = arg else {
return ReadSecretResult::Err(ReadSecretError::InvalidArgument("read output", arg));
};
let secret = match io {
Ok(secret) => secret,
Err(entry) => return ReadSecretResult::Io(KeyringIo::Read(Err(entry))),
};
trace!("resume after reading keyring entry");
ReadSecretResult::Ok(secret)
}
}