use std::collections::HashMap; use std::io; use crate::v8::{self, Global, WasmStreaming}; const MAX_ID: u64 = 9_007_199_254_740_991; #[doc(hidden)] pub struct WasmStreamingStart { pub id: u64, pub callback: Option>, } #[doc(hidden)] pub struct WasmStreamingStartError { pub message: String, pub stream: WasmStreaming, } #[derive(Default)] pub struct WasmStreamingRegistry { next_id: u64, callback: Option>, streams: HashMap>, } impl WasmStreamingRegistry { pub(crate) fn is_empty(&self) -> bool { self.callback.is_none() && self.streams.is_empty() && self.next_id == 0 } pub fn register(&mut self, callback: Global) -> io::Result<()> { if self.callback.is_some() { return Err(io::Error::other( "Wasm streaming callback is already registered", )); } self.callback = Some(callback); Ok(()) } pub fn start( &mut self, stream: WasmStreaming, ) -> Result { let callback = self.callback.as_ref().cloned(); let Some(id) = self.next_id.checked_add(1).filter(|id| *id <= MAX_ID) else { return Err(WasmStreamingStartError { message: "Wasm streaming resource IDs exhausted".to_owned(), stream, }); }; self.next_id = id; self.streams.insert(id, stream); Ok(WasmStreamingStart { id, callback }) } pub fn stream_mut(&mut self, id: u64) -> io::Result<&mut WasmStreaming> { self.streams .get_mut(&id) .ok_or_else(|| io::Error::other("Wasm streaming resource is closed")) } pub fn finish(&mut self, id: u64) -> io::Result<()> { self.streams .remove(&id) .ok_or_else(|| io::Error::other("Wasm streaming resource is closed"))? .finish(); Ok(()) } pub fn abort(&mut self, id: u64, exception: v8::Local) -> io::Result<()> { self.streams .remove(&id) .ok_or_else(|| io::Error::other("Wasm streaming resource is closed"))? .abort(Some(exception)); Ok(()) } }