blitz_shell/
net.rs

1use std::sync::Arc;
2
3use blitz_dom::net::Resource;
4use blitz_traits::net::NetCallback;
5use winit::event_loop::EventLoopProxy;
6
7use crate::BlitzShellEvent;
8
9/// A NetCallback that injects the fetched Resource into our winit event loop
10pub struct BlitzShellNetCallback(EventLoopProxy<BlitzShellEvent>);
11
12impl BlitzShellNetCallback {
13    pub fn new(proxy: EventLoopProxy<BlitzShellEvent>) -> Self {
14        Self(proxy)
15    }
16
17    pub fn shared(proxy: EventLoopProxy<BlitzShellEvent>) -> Arc<dyn NetCallback<Resource>> {
18        Arc::new(Self(proxy))
19    }
20}
21impl NetCallback<Resource> for BlitzShellNetCallback {
22    fn call(&self, doc_id: usize, result: Result<Resource, Option<String>>) {
23        // TODO: handle error case
24        if let Ok(data) = result {
25            self.0
26                .send_event(BlitzShellEvent::ResourceLoad { doc_id, data })
27                .unwrap()
28        }
29    }
30}
31
32#[cfg(feature = "data-uri")]
33mod data_uri_net_provider {
34    //! Data-URI only networking for Blitz
35    //!
36    //! Provides an implementation of the [`blitz_traits::net::NetProvider`] trait.
37
38    use blitz_traits::net::{Bytes, NetCallback, NetHandler, NetProvider, Request};
39    use data_url::DataUrl;
40    use std::sync::Arc;
41
42    pub struct DataUriNetProvider<D> {
43        resource_callback: Arc<dyn NetCallback<D>>,
44    }
45    impl<D: 'static> DataUriNetProvider<D> {
46        pub fn new(resource_callback: Arc<dyn NetCallback<D>>) -> Self {
47            Self { resource_callback }
48        }
49        pub fn shared(res_callback: Arc<dyn NetCallback<D>>) -> Arc<dyn NetProvider<D>> {
50            Arc::new(Self::new(res_callback))
51        }
52    }
53
54    impl<D: 'static> NetProvider<D> for DataUriNetProvider<D> {
55        fn fetch(&self, doc_id: usize, request: Request, handler: Box<dyn NetHandler<D>>) {
56            let callback = &self.resource_callback;
57            match request.url.scheme() {
58                "data" => {
59                    let Ok(data_url) = DataUrl::process(request.url.as_str()) else {
60                        callback.call(doc_id, Err(Some(String::from("Failed to parse data uri"))));
61                        return;
62                    };
63                    let Ok(decoded) = data_url.decode_to_vec() else {
64                        callback.call(doc_id, Err(Some(String::from("Failed to decode data uri"))));
65                        return;
66                    };
67                    let bytes = Bytes::from(decoded.0);
68                    handler.bytes(doc_id, bytes, Arc::clone(callback));
69                }
70                _ => {
71                    callback.call(doc_id, Err(Some(String::from("UnsupportedScheme"))));
72                }
73            };
74        }
75    }
76}
77#[cfg(feature = "data-uri")]
78pub use data_uri_net_provider::DataUriNetProvider;