mirror of https://codeberg.org/topola/topola.git
egui/file_handler: run parsing in file loader thread
- also embed I/O errors with other errors
This commit is contained in:
parent
1a46504dd5
commit
25a692aab9
|
|
@ -9,8 +9,11 @@ use std::{
|
||||||
use unic_langid::{langid, LanguageIdentifier};
|
use unic_langid::{langid, LanguageIdentifier};
|
||||||
|
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{invoker::Invoker, Autorouter},
|
autorouter::{history::History, invoker::Invoker, Autorouter},
|
||||||
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
specctra::{
|
||||||
|
design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
||||||
|
mesadata::SpecctraMesadata,
|
||||||
|
},
|
||||||
stepper::Step,
|
stepper::Step,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -38,12 +41,12 @@ pub struct App {
|
||||||
maybe_activity: Option<ActivityStepperWithStatus>,
|
maybe_activity: Option<ActivityStepperWithStatus>,
|
||||||
|
|
||||||
content_channel: (
|
content_channel: (
|
||||||
Sender<std::io::Result<FileHandlerData>>,
|
Sender<Result<SpecctraDesign, SpecctraLoadingError>>,
|
||||||
Receiver<std::io::Result<FileHandlerData>>,
|
Receiver<Result<SpecctraDesign, SpecctraLoadingError>>,
|
||||||
),
|
),
|
||||||
history_channel: (
|
history_channel: (
|
||||||
Sender<std::io::Result<FileHandlerData>>,
|
Sender<std::io::Result<Result<History, serde_json::Error>>>,
|
||||||
Receiver<std::io::Result<FileHandlerData>>,
|
Receiver<std::io::Result<Result<History, serde_json::Error>>>,
|
||||||
),
|
),
|
||||||
|
|
||||||
viewport: Viewport,
|
viewport: Viewport,
|
||||||
|
|
@ -109,13 +112,23 @@ impl App {
|
||||||
fn update_state(&mut self) -> bool {
|
fn update_state(&mut self) -> bool {
|
||||||
if let Ok(data) = self.content_channel.1.try_recv() {
|
if let Ok(data) = self.content_channel.1.try_recv() {
|
||||||
match data {
|
match data {
|
||||||
Ok(data) => match self.load_specctra_dsn(data) {
|
Ok(design) => match self.load_specctra_dsn(design) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.error_dialog.push_error("tr-module-specctra-dsn-file-loader", err);
|
self.error_dialog.push_error("tr-module-specctra-dsn-file-loader", err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(SpecctraLoadingError::Parse(err)) => {
|
||||||
|
self.error_dialog.push_error(
|
||||||
|
"tr-module-specctra-dsn-file-loader",
|
||||||
|
format!(
|
||||||
|
"{}; {}",
|
||||||
|
self.translator.text("tr-error_failed-to-parse-as-specctra-dsn"),
|
||||||
|
err
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(SpecctraLoadingError::Io(err)) => {
|
||||||
self.error_dialog.push_error(
|
self.error_dialog.push_error(
|
||||||
"tr-module-specctra-dsn-file-loader",
|
"tr-module-specctra-dsn-file-loader",
|
||||||
format!("{}; {}", self.translator.text("tr-error_unable-to-read-file"), err),
|
format!("{}; {}", self.translator.text("tr-error_unable-to-read-file"), err),
|
||||||
|
|
@ -125,18 +138,18 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(invoker) = self.arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
|
if let Some(invoker) = self.arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
|
||||||
if let Ok(input) = self.history_channel.1.try_recv() {
|
if let Ok(data) = self.history_channel.1.try_recv() {
|
||||||
let tr = &self.translator;
|
let tr = &self.translator;
|
||||||
match input {
|
match data {
|
||||||
Ok(bufread) => match serde_json::from_reader(bufread) {
|
Ok(Ok(data)) => {
|
||||||
Ok(res) => invoker.replay(res),
|
invoker.replay(data);
|
||||||
Err(err) => {
|
}
|
||||||
|
Ok(Err(err)) => {
|
||||||
self.error_dialog.push_error(
|
self.error_dialog.push_error(
|
||||||
"tr-module-history-file-loader",
|
"tr-module-history-file-loader",
|
||||||
format!("{}; {}", tr.text("tr-error_failed-to-parse-as-history-json"), err),
|
format!("{}; {}", tr.text("tr-error_failed-to-parse-as-history-json"), err),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.error_dialog.push_error(
|
self.error_dialog.push_error(
|
||||||
"tr-module-history-file-loader",
|
"tr-module-history-file-loader",
|
||||||
|
|
@ -161,10 +174,8 @@ impl App {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_specctra_dsn(&mut self, bufread: FileHandlerData) -> Result<(), String> {
|
fn load_specctra_dsn(&mut self, design: SpecctraDesign) -> Result<(), String> {
|
||||||
let tr = &self.translator;
|
let tr = &self.translator;
|
||||||
let design = SpecctraDesign::load(bufread)
|
|
||||||
.map_err(|err| format!("{}; {}", tr.text("tr-error_failed-to-parse-as-specctra-dsn"), err))?;
|
|
||||||
let board = design.make_board();
|
let board = design.make_board();
|
||||||
let overlay = Overlay::new(&board)
|
let overlay = Overlay::new(&board)
|
||||||
.map_err(|err| format!("{}; {}", tr.text("tr-error_unable-to-initialize-overlay"), err))?;
|
.map_err(|err| format!("{}; {}", tr.text("tr-error_unable-to-initialize-overlay"), err))?;
|
||||||
|
|
|
||||||
|
|
@ -46,19 +46,28 @@ impl io::BufRead for FileHandlerData {
|
||||||
fhd_forward!(fn consume(&mut self, amt: usize));
|
fhd_forward!(fn consume(&mut self, amt: usize));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn push_file_to_read(
|
#[inline]
|
||||||
|
pub async fn push_file_to_read<R, E, C>(
|
||||||
file_handle: &rfd::FileHandle,
|
file_handle: &rfd::FileHandle,
|
||||||
sender: Sender<std::io::Result<FileHandlerData>>,
|
sender: Sender<Result<R, E>>,
|
||||||
) {
|
callback: C,
|
||||||
let _ = sender.send(handle_text(&file_handle).await);
|
) where
|
||||||
|
E: From<std::io::Error>,
|
||||||
|
C: FnOnce(FileHandlerData) -> Result<R, E>,
|
||||||
|
{
|
||||||
|
let _ = sender.send(handle_text(&file_handle, callback).await);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_text(file_handle: &rfd::FileHandle) -> std::io::Result<FileHandlerData> {
|
async fn handle_text<R, E, C>(file_handle: &rfd::FileHandle, callback: C) -> Result<R, E>
|
||||||
|
where
|
||||||
|
E: From<std::io::Error>,
|
||||||
|
C: FnOnce(FileHandlerData) -> Result<R, E>,
|
||||||
|
{
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let res = FileHandlerData::File(io::BufReader::new(std::fs::File::open(file_handle.path())?));
|
let res = FileHandlerData::File(io::BufReader::new(std::fs::File::open(file_handle.path())?));
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
let res = FileHandlerData::Contents(io::Cursor::new(file_handle.read().await));
|
let res = FileHandlerData::Contents(io::Cursor::new(file_handle.read().await));
|
||||||
|
|
||||||
Ok(res)
|
callback(res)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ use std::{
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
command::Command,
|
command::Command,
|
||||||
|
history::History,
|
||||||
invoker::{Invoker, InvokerError},
|
invoker::{Invoker, InvokerError},
|
||||||
AutorouterOptions,
|
AutorouterOptions,
|
||||||
},
|
},
|
||||||
router::RouterOptions,
|
router::RouterOptions,
|
||||||
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
specctra::{
|
||||||
|
design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
||||||
|
mesadata::SpecctraMesadata,
|
||||||
|
},
|
||||||
stepper::Abort,
|
stepper::Abort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -59,8 +63,8 @@ impl MenuBar {
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
tr: &Translator,
|
tr: &Translator,
|
||||||
content_sender: Sender<std::io::Result<FileHandlerData>>,
|
content_sender: Sender<Result<SpecctraDesign, SpecctraLoadingError>>,
|
||||||
history_sender: Sender<std::io::Result<FileHandlerData>>,
|
history_sender: Sender<std::io::Result<Result<History, serde_json::Error>>>,
|
||||||
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
|
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
|
||||||
maybe_activity: &mut Option<ActivityStepperWithStatus>,
|
maybe_activity: &mut Option<ActivityStepperWithStatus>,
|
||||||
viewport: &mut Viewport,
|
viewport: &mut Viewport,
|
||||||
|
|
@ -239,7 +243,10 @@ impl MenuBar {
|
||||||
|
|
||||||
execute(async move {
|
execute(async move {
|
||||||
if let Some(file_handle) = task.await {
|
if let Some(file_handle) = task.await {
|
||||||
push_file_to_read(&file_handle, content_sender).await;
|
push_file_to_read(&file_handle, content_sender, |data| {
|
||||||
|
SpecctraDesign::load(data)
|
||||||
|
})
|
||||||
|
.await;
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -278,7 +285,14 @@ impl MenuBar {
|
||||||
|
|
||||||
execute(async move {
|
execute(async move {
|
||||||
if let Some(file_handle) = task.await {
|
if let Some(file_handle) = task.await {
|
||||||
push_file_to_read(&file_handle, history_sender).await;
|
push_file_to_read(&file_handle, history_sender, |data| {
|
||||||
|
match serde_json::from_reader(data) {
|
||||||
|
Ok(history) => Ok(Ok(history)),
|
||||||
|
Err(err) if err.is_io() => Err(err.into()),
|
||||||
|
Err(err) => Ok(Err(err)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
pub use read::ParseErrorContext;
|
||||||
|
|
||||||
/// Errors raised by [`SpecctraDesign::load`]
|
/// Errors raised by [`SpecctraDesign::load`]
|
||||||
|
#[derive(Error, Debug)]
|
||||||
pub enum LoadingError {
|
pub enum LoadingError {
|
||||||
/// I/O file reading error from [`std::io::Error`]
|
/// I/O file reading error from [`std::io::Error`]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue