DelSkayn / rquickjs

High level bindings to the quickjs javascript engine
MIT License
434 stars 59 forks source link

Trait to prototype support #218

Open stevefan1999-personal opened 9 months ago

stevefan1999-personal commented 9 months ago

I have some overlapping functionality with TcpStream and File, they are both implementing Read & Write (or AsyncRead and AsyncWrite) respectively. We need to make sure that the code can be reused to NRY.

stevefan1999-personal commented 9 months ago

This is my workaround for now:

#[derive(Clone, From, Into, Deref, DerefMut)]
pub struct AsyncReadWrapper(Arc<RwLock<dyn AsyncRead + Unpin>>);

impl AsyncReadWrapper {
    pub async fn read_to_end(self, ctx: Ctx<'_>) -> rquickjs::Result<Vec<u8>> {
        let mut buf = vec![];
        let mut write = self.write().await;
        write
            .read_to_end(&mut buf)
            .with_cancellation(&ctx.worlds_end())
            .await??;
        Ok(buf)
    }

    pub async fn read_to_string(self, ctx: Ctx<'_>) -> rquickjs::Result<String> {
        let mut str = String::new();
        let mut write = self.write().await;
        write
            .read_to_string(&mut str)
            .with_cancellation(&ctx.worlds_end())
            .await??;
        Ok(str)
    }

    pub async fn read<'js>(
        self,
        bytes: usize,
        ctx: Ctx<'js>,
    ) -> rquickjs::Result<TypedArray<'js, u8>> {
        let mut buf = vec![0; bytes];
        let mut write = self.write().await;
        write
            .read(&mut buf)
            .with_cancellation(&ctx.worlds_end())
            .await??;
        TypedArray::new(ctx, buf)
    }
}

#[derive(Trace, Derivative, From, Into, Deref, DerefMut)]
#[derivative(Clone, Debug)]
#[rquickjs::class(rename = "TcpStream")]
pub struct TcpStreamWrapper {
    #[qjs(skip_trace)]
    stream: Arc<RwLock<TcpStream>>,
}

#[rquickjs::methods]
impl TcpStreamWrapper {
    #[qjs(constructor)]
    pub fn new() {}

    pub async fn read_to_end(self, ctx: Ctx<'_>) -> rquickjs::Result<Vec<u8>> {
        AsyncReadWrapper(self.stream).read_to_end(ctx).await
    }
}

Need to repeat the boilerplate for AsyncReadWrapper though