gpg-rs / gpgme

GPGme bindings for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

wrap gpgme_set_passphrase_cb so that it can be called directly

khimaros opened this issue · comments

while Context::with_passphrase_provider() is useful, there are use patterns which it does not serve particularly well. It would be helpful to have an analog to Context::set_pinentry_mode() for setting the passphrase callback. Upstream API documentation: https://www.gnupg.org/documentation/manuals/gpgme/Passphrase-Callback.html#Passphrase-Callback

The main problem with providing a minimal wrapper for gpgme_set_passphrase_cb is that it does not take ownership of the callback data. This means the lifetime of the callback data must be managed manually and the only ways to do that safely in rust for non-static data is by storing the data alongside the context or by using a closure à la scoped threads. The first method would require either a secondary context wrapper (possible but cumbersome) or additional overhead for every instance of a Context. A wrapper that takes a static reference may also be possible but it would not be able to catch and resume panics (at least not without leaking memory every time a callback is set). If this still sounds useful, I would be willing to add it though.

Context Wrapper:

impl Context {
    pub fn set_passphrase_provider<P>(self, provider: P) -> ContextWithPassphraseProvider<P>
    where P: PassphraseProvider {
        ...
    }
}

pub ContextWithPassphraseProvider<P> {
    ctx: Context,
    provider: P,
}

impl Deref for ContextWithPassphraseProvider {
    type Target = Context;
    ...
}

Static reference:

impl Context {
    pub fn set_passphrase_provider<P>(&mut self, provider: &'static mut P)
    where P: PassphraseProvider {
        ...
    }
}