fn0-ski 0.1.2

Minimal Winter CG Compatible Runtime
use crate::Body;
use deno_core::*;
use deno_error::JsErrorBox;
use http_body_util::BodyExt;
use std::borrow::Cow;
use std::rc::Rc;

pub struct HttpBodyResource {
    pub body: Rc<AsyncRefCell<Body>>,
    cancel: Rc<CancelHandle>,
}

impl HttpBodyResource {
    pub fn new(body: Body) -> Self {
        Self {
            body: Rc::new(AsyncRefCell::new(body)),
            cancel: CancelHandle::new_rc(),
        }
    }
}

impl Resource for HttpBodyResource {
    fn name(&self) -> Cow<'_, str> {
        "httpBody".into()
    }

    fn close(self: Rc<Self>) {
        self.cancel.cancel();
    }

    fn read(self: Rc<Self>, _limit: usize) -> AsyncResult<BufView> {
        let cancel = self.cancel.clone();
        Box::pin(
            async move {
                let mut body = self.body.borrow_mut().await;
                match body.frame().await {
                    Some(Ok(frame)) => frame
                        .into_data()
                        .map(BufView::from)
                        .map_err(|_| JsErrorBox::generic("Failed to get bytes from frame")),
                    Some(Err(e)) => Err(JsErrorBox::generic(format!("Stream error: {}", e))),
                    None => Ok(BufView::empty()),
                }
            }
            .try_or_cancel(cancel),
        )
    }
}