io_keyring/coroutines/
write.rs1use log::trace;
4use secrecy::SecretString;
5use thiserror::Error;
6
7use crate::{entry::KeyringEntry, io::KeyringIo};
8
9#[derive(Clone, Debug, Error)]
11pub enum WriteSecretError {
12 #[error("Invalid argument: expected {0}, got {1:?}")]
14 InvalidArgument(&'static str, KeyringIo),
15
16 #[error("Entry and secret not ready")]
18 NotReady,
19}
20
21#[derive(Clone, Debug)]
23pub enum WriteSecretResult {
24 Ok(()),
26
27 Io(KeyringIo),
29
30 Err(WriteSecretError),
32}
33
34#[derive(Clone, Debug)]
36pub struct WriteSecret {
37 secret: Option<(KeyringEntry, SecretString)>,
38}
39
40impl WriteSecret {
41 pub fn new(entry: KeyringEntry, secret: impl Into<SecretString>) -> Self {
43 let secret = Some((entry, secret.into()));
44 Self { secret }
45 }
46
47 pub fn resume(&mut self, arg: Option<KeyringIo>) -> WriteSecretResult {
49 let Some(arg) = arg else {
50 let Some(secret) = self.secret.take() else {
51 return WriteSecretResult::Err(WriteSecretError::NotReady);
52 };
53
54 trace!("need I/O to write secret into keyring entry");
55 return WriteSecretResult::Io(KeyringIo::Write(Err(secret)));
56 };
57
58 let KeyringIo::Write(io) = arg else {
59 let err = WriteSecretError::InvalidArgument("write output", arg);
60 return WriteSecretResult::Err(err);
61 };
62
63 if let Err((entry, secret)) = io {
64 return WriteSecretResult::Io(KeyringIo::Write(Err((entry, secret))));
65 }
66
67 trace!("resume after writing secret into keyring entry");
68 WriteSecretResult::Ok(())
69 }
70}