///|
/// Native BytesFetcher using function injection.
/// Reads files synchronously and delivers callbacks via deferred queue.
///|
struct DeferredResult {
id : Int
data : Bytes?
on_progress : (FetchProgress) -> Unit
on_complete : (Bytes?) -> Unit
mut cancelled : Bool
}
///|
pub struct NativeFetcher {
read_file_fn : (String) -> Bytes?
mut next_id : Int
deferred : Array[DeferredResult]
}
///|
pub fn new_native_fetcher(read_file_fn : (String) -> Bytes?) -> NativeFetcher {
{ read_file_fn, next_id: 1, deferred: [] }
}
///|
pub impl BytesFetcher for NativeFetcher with fetch(
self,
url,
on_progress,
on_complete,
) {
let id = self.next_id
self.next_id = self.next_id + 1
let data = (self.read_file_fn)(url)
self.deferred.push({ id, data, on_progress, on_complete, cancelled: false })
{ id, }
}
///|
pub impl BytesFetcher for NativeFetcher with cancel(self, handle) {
for entry in self.deferred {
if entry.id == handle.id {
entry.cancelled = true
}
}
}
///|
pub impl BytesFetcher for NativeFetcher with poll(self) {
let pending = self.deferred.drain(0, self.deferred.length())
for entry in pending {
if entry.cancelled {
continue
}
match entry.data {
Some(bytes) => {
let total = bytes.length()
(entry.on_progress)({ loaded: total, total })
(entry.on_complete)(Some(bytes))
}
None => (entry.on_complete)(None)
}
}
}