1pub use bytes::Bytes;
4pub use http::{self, HeaderMap, HeaderValue, Method};
5use serde::{
6 Serialize,
7 ser::{SerializeSeq, SerializeTuple},
8};
9use std::sync::{
10 Arc,
11 atomic::{AtomicBool, Ordering},
12};
13use std::{ops::Deref, path::PathBuf};
14pub use url::Url;
15
16pub trait CookieJar: Send + Sync + 'static {
19 fn cookies_header(&self, url: &Url) -> Option<HeaderValue>;
21
22 fn store_from_response(&self, url: &Url, headers: &HeaderMap);
24}
25
26pub trait NetProvider: Send + Sync + 'static {
30 fn fetch(&self, doc_id: usize, request: Request, handler: Box<dyn NetHandler>);
31
32 fn is_noop(&self) -> bool {
38 false
39 }
40}
41
42pub trait NetHandler: Send + Sync + 'static {
45 fn bytes(self: Box<Self>, resolved_url: String, bytes: Bytes);
46}
47
48pub trait NetWaker: Send + Sync + 'static {
51 fn wake(&self, client_id: usize);
52}
53
54impl<F: Fn(usize) + Send + Sync + 'static> NetWaker for F {
55 fn wake(&self, doc_id: usize) {
56 self(doc_id)
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
62pub enum RequestDestination {
63 #[default]
64 Empty,
65 Document,
66 Iframe,
67 Style,
68 Script,
69 Image,
70 Font,
71 Audio,
72 Video,
73 Track,
74 Manifest,
75}
76
77impl RequestDestination {
78 pub fn as_str(self) -> &'static str {
79 match self {
80 Self::Empty => "empty",
81 Self::Document => "document",
82 Self::Iframe => "iframe",
83 Self::Style => "style",
84 Self::Script => "script",
85 Self::Image => "image",
86 Self::Font => "font",
87 Self::Audio => "audio",
88 Self::Video => "video",
89 Self::Track => "track",
90 Self::Manifest => "manifest",
91 }
92 }
93}
94
95#[non_exhaustive]
96#[derive(Debug, Clone)]
97pub struct Request {
99 pub url: Url,
100 pub method: Method,
101 pub content_type: Option<String>,
102 pub headers: HeaderMap,
103 pub body: Body,
104 pub signal: Option<AbortSignal>,
105 pub destination: RequestDestination,
106}
107impl Request {
108 pub fn get(url: Url) -> Self {
110 Self {
111 url,
112 method: Method::GET,
113 content_type: None,
114 headers: HeaderMap::new(),
115 body: Body::Empty,
116 signal: None,
117 destination: RequestDestination::default(),
118 }
119 }
120
121 pub fn destination(mut self, d: RequestDestination) -> Self {
122 self.destination = d;
123 self
124 }
125
126 pub fn signal(mut self, signal: AbortSignal) -> Self {
127 self.signal = Some(signal);
128 self
129 }
130}
131
132#[derive(Debug, Clone)]
133pub enum Body {
134 Bytes(Bytes),
135 Form(FormData),
136 Empty,
137}
138
139#[derive(Debug, Clone, PartialEq, Default)]
141pub struct FormData(pub Vec<Entry>);
142impl FormData {
143 pub fn new() -> Self {
145 FormData(Vec::new())
146 }
147}
148impl Serialize for FormData {
149 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: serde::Serializer,
152 {
153 let mut seq_serializer = serializer.serialize_seq(Some(self.len()))?;
154 for entry in &self.0 {
155 seq_serializer.serialize_element(entry)?;
156 }
157 seq_serializer.end()
158 }
159}
160impl Deref for FormData {
161 type Target = Vec<Entry>;
162
163 fn deref(&self) -> &Self::Target {
164 &self.0
165 }
166}
167
168#[derive(Debug, Clone, PartialEq)]
170pub struct Entry {
171 pub name: String,
172 pub value: EntryValue,
173}
174impl Serialize for Entry {
175 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176 where
177 S: serde::Serializer,
178 {
179 let mut serializer = serializer.serialize_tuple(2)?;
180 serializer.serialize_element(&self.name)?;
181 match &self.value {
182 EntryValue::String(s) => serializer.serialize_element(s)?,
183 EntryValue::File(p) => serializer.serialize_element(p.to_str().unwrap_or_default())?,
184 EntryValue::EmptyFile => serializer.serialize_element("")?,
185 }
186 serializer.end()
187 }
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub enum EntryValue {
192 String(String),
193 File(PathBuf),
194 EmptyFile,
195}
196impl AsRef<str> for EntryValue {
197 fn as_ref(&self) -> &str {
198 match self {
199 EntryValue::String(s) => s,
200 EntryValue::File(p) => p.to_str().unwrap_or_default(),
201 EntryValue::EmptyFile => "",
202 }
203 }
204}
205
206impl From<&str> for EntryValue {
207 fn from(value: &str) -> Self {
208 EntryValue::String(value.to_string())
209 }
210}
211impl From<PathBuf> for EntryValue {
212 fn from(value: PathBuf) -> Self {
213 EntryValue::File(value)
214 }
215}
216
217#[derive(Default)]
219pub struct DummyNetProvider;
220impl NetProvider for DummyNetProvider {
221 fn fetch(&self, _doc_id: usize, _request: Request, _handler: Box<dyn NetHandler>) {}
222 fn is_noop(&self) -> bool {
223 true
224 }
225}
226
227#[derive(Debug, Default)]
233pub struct AbortController {
234 pub signal: AbortSignal,
235}
236
237impl AbortController {
238 pub fn abort(self) {
244 self.signal.0.store(true, Ordering::SeqCst);
245 }
246}
247
248#[derive(Debug, Default, Clone)]
253pub struct AbortSignal(Arc<AtomicBool>);
254
255impl AbortSignal {
256 pub fn aborted(&self) -> bool {
259 self.0.load(Ordering::SeqCst)
260 }
261}