use std::{ collections::HashMap, future::Future, pin::Pin, sync::{ mpsc, mpsc::{Receiver, Sender}, }, }; use serde::{Deserialize, Serialize}; use crate::{ coords::WorldTileCoords, io::{ source_client::{HttpSourceClient, SourceClient}, transferables::{DefaultTransferables, Transferables}, TileRequest, }, Environment, HttpClient, Scheduler, }; /// The result of the tessellation of a tile. /// `TessellatedLayer` contains the result of the tessellation for a specific layer, otherwise /// `UnavailableLayer` if the layer doesn't exist. #[derive(Clone)] pub enum Message { TileTessellated(T::TileTessellated), UnavailableLayer(T::UnavailableLayer), TessellatedLayer(T::TessellatedLayer), } #[derive(Clone, Serialize, Deserialize)] pub enum Input { TileRequest(TileRequest), } pub trait Context: Send + 'static { fn send(&self, data: Message); fn source_client(&self) -> &SourceClient; } #[cfg(not(feature = "no-thread-safe-futures"))] pub type AsyncProcedureFuture = Pin + Send + 'static)>>; #[cfg(feature = "no-thread-safe-futures")] pub type AsyncProcedureFuture = Pin + 'static)>>; pub type AsyncProcedure = fn(input: Input, context: C) -> AsyncProcedureFuture; pub trait AsyncProcedureCall: 'static { type Context: Context + Send; fn receive(&mut self) -> Option>; fn schedule(&self, input: Input, procedure: AsyncProcedure); } #[derive(Clone)] pub struct SchedulerContext { sender: Sender>, source_client: SourceClient, } impl Context for SchedulerContext { fn send(&self, data: Message) { self.sender.send(data).unwrap(); // FIXME (wasm-executor): Remove unwrap } fn source_client(&self) -> &SourceClient { &self.source_client } } pub struct SchedulerAsyncProcedureCall { channel: ( Sender>, Receiver>, ), http_client: HC, scheduler: S, } impl SchedulerAsyncProcedureCall { pub fn new(http_client: HC, scheduler: S) -> Self { Self { channel: mpsc::channel(), http_client, scheduler, } } } impl AsyncProcedureCall for SchedulerAsyncProcedureCall { type Context = SchedulerContext; fn receive(&mut self) -> Option> { let transferred = self.channel.1.try_recv().ok()?; Some(transferred) } fn schedule(&self, input: Input, procedure: AsyncProcedure) { let sender = self.channel.0.clone(); let client = self.http_client.clone(); // FIXME (wasm-executor): do not clone each time self.scheduler .schedule(move || async move { (procedure)( input, SchedulerContext { sender, source_client: SourceClient::Http(HttpSourceClient::new(client)), }, ) .await; }) .unwrap(); } }