//! Keyring to perform rpgp operations with. use anyhow::Result; use crate::context::Context; use crate::key::DcKey; /// An in-memory keyring. /// /// Instances are usually constructed just for the rpgp operation and /// short-lived. #[derive(Clone, Debug, Default)] pub struct Keyring where T: DcKey, { keys: Vec, } impl Keyring where T: DcKey, { /// New empty keyring. pub fn new() -> Keyring { Keyring { keys: Vec::new() } } /// Create a new keyring with the the user's secret key loaded. pub async fn new_self(context: &Context) -> Result> { let mut keyring: Keyring = Keyring::new(); keyring.load_self(context).await?; Ok(keyring) } /// Load the user's key into the keyring. pub async fn load_self(&mut self, context: &Context) -> Result<()> { self.add(T::load_self(context).await?); Ok(()) } /// Add a key to the keyring. pub fn add(&mut self, key: T) { self.keys.push(key); } pub fn len(&self) -> usize { self.keys.len() } pub fn is_empty(&self) -> bool { self.keys.is_empty() } /// A vector with reference to all the keys in the keyring. pub fn keys(&self) -> &[T] { &self.keys } } #[cfg(test)] mod tests { use super::*; use crate::key::{SignedPublicKey, SignedSecretKey}; use crate::test_utils::{alice_keypair, TestContext}; #[test] fn test_keyring_add_keys() { let alice = alice_keypair(); let mut pub_ring: Keyring = Keyring::new(); pub_ring.add(alice.public.clone()); assert_eq!(pub_ring.keys(), [alice.public]); let mut sec_ring: Keyring = Keyring::new(); sec_ring.add(alice.secret.clone()); assert_eq!(sec_ring.keys(), [alice.secret]); } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_keyring_load_self() { // new_self() implies load_self() let t = TestContext::new_alice().await; let alice = alice_keypair(); let pub_ring: Keyring = Keyring::new_self(&t).await.unwrap(); assert_eq!(pub_ring.keys(), [alice.public]); let sec_ring: Keyring = Keyring::new_self(&t).await.unwrap(); assert_eq!(sec_ring.keys(), [alice.secret]); } }