str4d / rage

A simple, secure and modern file encryption tool (and Rust library) with small explicit keys, no config options, and UNIX-style composability.
https://age-encryption.org/v1
Apache License 2.0
2.53k stars 97 forks source link

age-plugin: Cannot create a plugin with *no* RecipientPlugin state #494

Closed wiktor-k closed 1 month ago

wiktor-k commented 4 months ago

Environment

Hi, I'm using age-plugin = "0.5.0"

What were you trying to do

I'm working on an age plugin which only has identity state transition (not recipient) since it works with ed25519 keys.

There's this fragment of code:

    if let Some(state_machine) = opts.age_plugin {
        return Ok(run_state_machine(
            &state_machine,
            Some(|| RecipientPlugin),
            Some(|| IdentityPlugin { cards: vec![] }),
        )?);
    }

Full sample here: https://github.com/wiktor-k/age-plugin-openpgp-card/blob/fd309b4140377c6515f9bd22deceb8e3cead02ad/src/main.rs#L244-L250

And I want to set Some(|| RecipientPlugin) to None (at least that's what I think it's for) but then...

What happened

$ cargo check
    Checking age-plugin-openpgp-card v0.1.0 (/home/wiktor/src/meta/age-plugin-openpgp-card)
error[E0283]: type annotations needed
   --> src/main.rs:245:19
    |
245 |           return Ok(run_state_machine(
    |  ___________________^
246 | |             &state_machine,
247 | |             None, //Some(|| RecipientPlugin),
248 | |             Some(|| IdentityPlugin { cards: vec![] }),
249 | |         )?);
    | |_________^ cannot infer type for type parameter `R` declared on the function `run_state_machine`
    |
    = note: cannot satisfy `_: RecipientPluginV1`
    = help: the trait `RecipientPluginV1` is implemented for `RecipientPlugin`
note: required by a bound in `run_state_machine`
   --> /home/wiktor/.cargo/registry/src/index.crates.io-6f17d22bba15001f/age-plugin-0.5.0/src/lib.rs:212:29
    |
212 | pub fn run_state_machine<R: recipient::RecipientPluginV1, I: identity::IdentityPluginV1>(
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `run_state_machine`

error[E0283]: type annotations needed
   --> src/main.rs:247:13
    |
245 |         return Ok(run_state_machine(
    |                   ----------------- required by a bound introduced by this call
246 |             &state_machine,
247 |             None, //Some(|| RecipientPlugin),
    |             ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
    |
    = note: multiple `impl`s satisfying `_: FnOnce()` found in the following crates: `alloc`, `core`:
            - impl<A, F> FnOnce<A> for &F
              where A: Tuple, F: Fn<A>, F: ?Sized;
            - impl<A, F> FnOnce<A> for &mut F
              where A: Tuple, F: FnMut<A>, F: ?Sized;
            - impl<Args, F, A> FnOnce<Args> for Box<F, A>
              where Args: Tuple, F: FnOnce<Args>, A: Allocator, F: ?Sized;
            - impl<F, Args> FnOnce<Args> for Exclusive<F>
              where F: FnOnce<Args>, Args: Tuple;
            - impl<R, F> FnOnce<()> for AssertUnwindSafe<F>
              where <F as FnOnce<()>>::Output == R, F: FnOnce();
note: required by a bound in `run_state_machine`
   --> /home/wiktor/.cargo/registry/src/index.crates.io-6f17d22bba15001f/age-plugin-0.5.0/src/lib.rs:214:31
    |
212 | pub fn run_state_machine<R: recipient::RecipientPluginV1, I: identity::IdentityPluginV1>(
    |        ----------------- required by a bound in this function
213 |     state_machine: &str,
214 |     recipient_v1: Option<impl FnOnce() -> R>,
    |                               ^^^^^^^^^^^^^ required by this bound in `run_state_machine`
help: consider specifying the generic argument
    |
247 |             None::<T>, //Some(|| RecipientPlugin),
    |                 +++++

For more information about this error, try `rustc --explain E0283`.
error: could not compile `age-plugin-openpgp-card` (bin "age-plugin-openpgp-card") due to 2 previous errors

It seems it still needs a type which implements the RecipientPlugin trait but I don't want to pass any :)

Please tell if I'm holding it wrong :)

Btw, any other remarks to the code are much appreciated, I'm working with the API for a couple of hours only and even though it works I'm not sure everything is kosher.

Btw 2: the age-plugin crate is really fantastic: I could build my own extension in a matter of hours. Rage is also very nice and debugging with AGEDEBUG=plugin RUST_LOG=debug has been a real time-saver!

Thank you very much! :bow:

str4d commented 1 month ago

Ah yep, this was me failing to address #387 correctly. I didn't actually add a test that my change (to make the arguments optional) was sufficient, and it turns out to be a terrible option to use. So I'm going to undo the change and instead add two separate helper methods for recipient-only and identity-only plugins.