Skip to content

Commit

Permalink
Revert split.
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Jan 15, 2020
1 parent 2e3e431 commit 8abdc9c
Showing 1 changed file with 153 additions and 55 deletions.
208 changes: 153 additions & 55 deletions src/services/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@

use super::Task;
use crate::callback::Callback;
use cfg_if::cfg_if;
use cfg_match::cfg_match;
use std::cmp;
use std::fmt;
use stdweb::unstable::TryInto;
use stdweb::web::event::LoadEndEvent;
pub use stdweb::web::{Blob, File, IBlob};
use stdweb::web::{FileReader, FileReaderReadyState, FileReaderResult, IEventTarget, TypedArray};
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
cfg_if! {
if #[cfg(feature = "std_web")] {
pub use stdweb::web::{Blob, File, IBlob};
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
use stdweb::unstable::TryInto;
use stdweb::web::event::LoadEndEvent;
use stdweb::web::{FileReader, FileReaderReadyState, FileReaderResult, IEventTarget, TypedArray};
} else if #[cfg(feature = "web_sys")] {
pub use web_sys::{Blob, File};
use gloo::events::EventListener;
use js_sys::Uint8Array;
use web_sys::{Event, FileReader};
}
}

/// Struct that represents data of a file.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -52,24 +63,55 @@ impl ReaderService {
/// Reads all bytes from a file and returns them with a callback.
pub fn read_file(&mut self, file: File, callback: Callback<FileData>) -> ReaderTask {
let file_reader = FileReader::new();
#[cfg(feature = "web_sys")]
let file_reader = file_reader.unwrap();
let reader = file_reader.clone();
let name = file.name();
file_reader.add_event_listener(move |_event: LoadEndEvent| match reader.result() {
Some(FileReaderResult::String(_)) => {
unreachable!();
}
Some(FileReaderResult::ArrayBuffer(buffer)) => {
let array: TypedArray<u8> = buffer.into();
let data = FileData {
name: name.clone(),
content: array.to_vec(),
};
callback.emit(data);
}
None => {}
});
let callback = move |#[cfg(feature = "std_web")] _event: LoadEndEvent,
#[cfg(feature = "web_sys")] _event: &Event| {
cfg_match! {
feature = "std_web" => ({
match reader.result() {
Some(FileReaderResult::String(_)) => {
unreachable!();
}
Some(FileReaderResult::ArrayBuffer(buffer)) => {
let array: TypedArray<u8> = buffer.into();
let data = FileData {
name: name.clone(),
content: array.to_vec(),
};
callback.emit(data);
}
None => {}
}
}),
feature = "web_sys" => ({
let array = Uint8Array::new_with_byte_offset(
&reader
.result()
.expect("`FileReader` hasn't finished loading"),
0,
);
let data = FileData {
name: name.clone(),
content: array.to_vec(),
};
callback.emit(data);
}),
};
};
#[cfg_attr(feature = "std_web", allow(unused_variables))]
let listener = cfg_match! {
feature = "std_web" => file_reader.add_event_listener(callback),
feature = "web_sys" => Some(EventListener::new(&file_reader, "loadend", callback)),
};
file_reader.read_as_array_buffer(&file).unwrap();
ReaderTask { file_reader }
ReaderTask {
file_reader,
#[cfg(feature = "web_sys")]
listener,
}
}

/// Reads data chunks from a file and returns them with a callback.
Expand All @@ -80,60 +122,108 @@ impl ReaderService {
chunk_size: usize,
) -> ReaderTask {
let file_reader = FileReader::new();
#[cfg(feature = "web_sys")]
let file_reader = file_reader.unwrap();
let name = file.name();
let mut position = 0;
let total_size = file.len() as usize;
let total_size = cfg_match! {
feature = "std_web" => file.len(),
feature = "web_sys" => file.size(),
} as usize;
let reader = file_reader.clone();
file_reader.add_event_listener(move |_event: LoadEndEvent| {
match reader.result() {
// This branch is used to start reading
Some(FileReaderResult::String(_)) => {
let started = FileChunk::Started { name: name.clone() };
callback.emit(started);
}
// This branch is used to send a chunk value
Some(FileReaderResult::ArrayBuffer(buffer)) => {
let array: TypedArray<u8> = buffer.into();
let chunk = FileChunk::DataChunk {
data: array.to_vec(),
progress: position as f32 / total_size as f32,
};
callback.emit(chunk);
}
None => {}
}
let callback = move |#[cfg(feature = "std_web")] _event: LoadEndEvent,
#[cfg(feature = "web_sys")] _event: &Event| {
cfg_match! {
feature = "std_web" => ({
match reader.result() {
// This branch is used to start reading
Some(FileReaderResult::String(_)) => {
let started = FileChunk::Started { name: name.clone() };
callback.emit(started);
}
// This branch is used to send a chunk value
Some(FileReaderResult::ArrayBuffer(buffer)) => {
let array: TypedArray<u8> = buffer.into();
let chunk = FileChunk::DataChunk {
data: array.to_vec(),
progress: position as f32 / total_size as f32,
};
callback.emit(chunk);
}
None => {}
}
}),
feature = "web_sys" => ({
let result = reader
.result()
.expect("`FileReader` hasn't finished loading");

if result.is_string() {
let started = FileChunk::Started { name: name.clone() };
callback.emit(started);
} else {
let array = Uint8Array::new_with_byte_offset(&result, 0);
let chunk = FileChunk::DataChunk {
data: array.to_vec(),
progress: position as f32 / total_size as f32,
};
callback.emit(chunk);
}
}),
};
// Read the next chunk
if position < total_size {
let file = &file;
let from = position;
let to = cmp::min(position + chunk_size, total_size);
position = to;
// TODO Implement `slice` method in `stdweb`
let blob: Blob = (js! {
return @{file}.slice(@{from as u32}, @{to as u32});
})
.try_into()
.unwrap();
let blob: Blob = cfg_match! {
feature = "std_web" => ({
// TODO Implement `slice` method in `stdweb`
let file = &file;
(js! {
return @{file}.slice(@{from as u32}, @{to as u32});
})
.try_into()
.unwrap()
}),
feature = "web_sys" => file.slice_with_i32_and_i32(from as _, to as _).unwrap(),
};
reader.read_as_array_buffer(&blob).unwrap();
} else {
let finished = FileChunk::Finished;
callback.emit(finished);
}
});
let blob: Blob = (js! {
return (new Blob());
})
.try_into()
.unwrap();
};
#[cfg_attr(feature = "std_web", allow(unused_variables))]
let listener = cfg_match! {
feature = "std_web" => file_reader.add_event_listener(callback),
feature = "web_sys" => Some(EventListener::new(&file_reader, "loadend", callback)),
};
let blob: Blob = cfg_match! {
feature = "std_web" => ({
(js! {
return (new Blob());
})
.try_into()
.unwrap()
}),
feature = "web_sys" => Blob::new().unwrap(),
};
file_reader.read_as_text(&blob).unwrap();
ReaderTask { file_reader }
ReaderTask {
file_reader,
#[cfg(feature = "web_sys")]
listener,
}
}
}

/// A handle to control reading.
#[must_use]
pub struct ReaderTask {
file_reader: FileReader,
#[cfg(feature = "web_sys")]
listener: Option<EventListener>,
}

impl fmt::Debug for ReaderTask {
Expand All @@ -144,11 +234,19 @@ impl fmt::Debug for ReaderTask {

impl Task for ReaderTask {
fn is_active(&self) -> bool {
self.file_reader.ready_state() == FileReaderReadyState::Loading
cfg_match! {
feature = "std_web" => self.file_reader.ready_state() == FileReaderReadyState::Loading,
feature = "web_sys" => self.file_reader.ready_state() == FileReader::LOADING,
}
}

fn cancel(&mut self) {
self.file_reader.abort();
drop(
self.listener
.take()
.expect("tried to cancel websocket twice"),
)
}
}

Expand Down

0 comments on commit 8abdc9c

Please sign in to comment.