dfinity / cdk-rs

Rust canister development kit for the Internet Computer.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use the lifetime as a public function's argument?

flyq opened this issue · comments

The code is:

#[derive(CandidType, Copy, Clone, Deserialize)]
struct SetNodeArgs<'a> {
    pub_key: &'a [u8],
    auth: bool
}
...

#[update]
#[candid_method(update)]
fn set_node(args: SetNodeArgs<'static>) -> bool {
    assert!(OWNER == api::caller());
    assert!(PublicKey::parse_slice(args.pub_key, None).is_ok());
    let nodes = storage::get_mut::<NodePub<'static>>();
    if args.auth {
        nodes.insert(args.pub_key);
    } else {
        nodes.remove(args.pub_key);
    }
    return true;
}

I want to a function's

error[E0308]: mismatched types
  --> src/main.rs:65:1
   |
65 | #[update]
   | ^^^^^^^^^ one type is more general than the other
   |
   = note: expected trait `ArgumentDecoder<'a>`
              found trait `ArgumentDecoder<'_>`
   = note: this error originates in the attribute macro `update` (in Nightly builds, run with -Z macro-backtrace for more info)

This would not be possible without a macro, so it is not possible with one either. SetNodeArgs<'static>, i.e. &'static [u8], means that the function would have to be called with memory that will be available forever, which isn't possible to provide. Somewhere this data must be owned. Since it must be deserialized to a vector anyway in order to provide it as a slice, it looks like the best option would be for SetNodeArgs to be unparameterized, and contain a Vec<u8>. I would hazard a guess that NodePub is designed the same way, and so must be redesigned the same way; I would hazard another guess that NodePub is designed the way that it is so you can return &'static [u8] from some function, but you should be able to do that anyway given a &'static NodePub (which is what storage::get returns).