rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.65k stars 1.05k forks source link

I don't know why `*arg1` does not live long enough. please help! I'am new guy of wasm-bindgen #2789

Closed kaneruan closed 2 years ago

kaneruan commented 2 years ago

Summary

#[wasm_bindgen] tell me *arg1 does not live long enough it's ok when i Comment out the #[wasm_bindgen] and#[wasm_bindgen(constructor)]; A clear and concise summary of your question.

Additional Details

#![allow(unused_variables)]
use std::{collections::HashMap, convert::TryFrom, pin::Pin};

use js_sys::{ArrayBuffer, Object};
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;

use wasm_bindgen::prelude::*;
use web_sys::AudioContext;
use web_sys::{window, AudioBuffer, Request, Response};

#[wasm_bindgen]
pub struct FmOsc {
    ctx: AudioContext,
    /// Overall gain (volume) control
    gain: web_sys::GainNode,

    dest: web_sys::AudioDestinationNode,
    buf_source: web_sys::AudioBufferSourceNode,
    buf_map: HashMap<String, AudioBuffer>,
}

impl Drop for FmOsc {
    fn drop(&mut self) {
        let _ = self.ctx.close();
    }
}

#[wasm_bindgen]
impl FmOsc {
    // #[wasm_bindgen]
   // loadBuffer from remote
    pub async fn loadBuffer(&mut self, src: &str) -> Result<(), JsValue> {
        let mut opts = web_sys::RequestInit::new();
        opts.method("GET");
        opts.mode(web_sys::RequestMode::Cors);
        let request = Request::new_with_str_and_init(src, &opts)?;
        let window = window().unwrap();
        let resp_val = JsFuture::from(window.fetch_with_request(&request)).await?;
        let resp: Response = resp_val.dyn_into()?;
        // let json = JsFuture::from(resp.json()?).await?;

        let buf_str = JsFuture::from(resp.array_buffer()?).await?;

        let buf: AudioBuffer = buf_str.into();
        let buf = self.decrypt(&buf).await;
        self.buf_map.insert(src.to_string(), buf);
        Ok(())
    }
   // play about the songurl
    #[wasm_bindgen]
    pub async fn play(&mut self, src: &str) -> Result<(), JsValue> {
        let buf = self.buf_map.get(src);
        if let Some(a) = buf {
            self.buf_source.set_buffer(buf);
            let rt = self.buf_source.start()?;
            self.gain.connect_with_audio_node(&self.dest);

            Ok(())
        } else {
            self.loadBuffer(src).await;

            let buf = self.buf_map.get(src);
            if let Some(a) = buf {
                self.buf_source.set_buffer(buf);
                let rt = self.buf_source.start()?;
                self.gain.connect_with_audio_node(&self.dest);
            } else {
            }
            // self.play(src).await;
            Ok(())
        }
    }
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<FmOsc, JsValue> {
        let ctx = web_sys::AudioContext::new()?;
        let dest = ctx.destination();
        let gain = ctx.create_gain()?;
        let buf_source = ctx.create_buffer_source()?;
        let buf_map: HashMap<String, AudioBuffer> = HashMap::new();

        Ok(FmOsc {
            ctx,
            dest,
            gain,
            buf_source,
            buf_map,
        })

        // Create our web audio objects.
    }
   // decrypt loaded buffer 
    async fn decrypt(&self, data: &AudioBuffer) -> AudioBuffer {
        let mut rand_arry = [0u8; 128];
        let window = web_sys::window().unwrap();
        let crypto = window.crypto().unwrap();
        let counter = crypto
            .get_random_values_with_u8_array(&mut rand_arry)
            .unwrap();
        let subtleCrypto = crypto.subtle();
        // al_r.serialize()
        // let mal = serde_json::from_str(s).unwrap();
        let al: Object = JsValue::from_serde(
            r#"{
            "name": "AES-CTR",
            "length": 128,
        }"#,
        )
        .unwrap()
        .into();
        let key_usages: JsValue = JsValue::from_serde(r#"["encrypt"]"#).unwrap().into();
        let s = "12132324".to_string();
        let key_data = js_sys::Uint8Array::from(s.as_bytes()).dyn_into().unwrap();
        let keyPromise = subtleCrypto
            .import_key_with_str(
                "raw",
                &key_data,
                "AES-CTR",
                true,
                &JsValue::from(r#"["encrypt"]"#),
            )
            .unwrap();
        let key = JsFuture::from(keyPromise)
            .await
            .unwrap()
            .dyn_into()
            .unwrap();

        let decryptedPromise = subtleCrypto
            .decrypt_with_object_and_buffer_source(&al, &key, data)
            .unwrap();
        let decryptedData: AudioBuffer = JsFuture::from(decryptedPromise).await.unwrap().into();
        decryptedData

    }
}
fn main() {}

Provide any additional details here. image

alexcrichton commented 2 years ago

This is a poor error message that needs to be improved but the bug is that async functions with self must be self-by-value, they can't have shared references.

kaneruan commented 2 years ago

@alexcrichton Are you have any idea to fix that? I I've been stuck here for a long time. 😭

alexcrichton commented 2 years ago

As I mentioned the methods must be self-by-value and the arguments can't have any references/lifetimes in them. Other than that I don't know what else to do.

kaneruan commented 2 years ago

thanks, I attempt to use Rc<RefCell<?>> to solve them, but I meet new question. #2791 https://github.com/rustwasm/wasm-bindgen/issues/2791

God! It's difficult to solve by myself.