diff --git a/app/src/main/rust/Cargo.toml b/app/src/main/rust/Cargo.toml
index 20ceaab47..f45f80063 100644
--- a/app/src/main/rust/Cargo.toml
+++ b/app/src/main/rust/Cargo.toml
@@ -19,7 +19,7 @@ serde_cbor = "0.11"
serde = { version = "1.0", features = ["derive"] }
[profile.release]
+panic = "abort"
strip = true
-opt-level = "s"
lto = true
codegen-units = 1
diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs
index 28b7e65cd..7cb6d2c85 100644
--- a/app/src/main/rust/src/lib.rs
+++ b/app/src/main/rust/src/lib.rs
@@ -18,7 +18,6 @@ use log::LevelFilter;
use serde::Serialize;
use std::ffi::c_void;
use std::io::Cursor;
-use std::panic::{catch_unwind, UnwindSafe};
use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
use std::str::from_utf8_unchecked;
use tl::{Bytes, Node, NodeHandle, Parser, VDom};
@@ -34,12 +33,6 @@ macro_rules! regex {
const EHGT_PREFIX: &str = "https://ehgt.org/";
const EX_PREFIX: &str = "https://s.exhentai.org/";
-fn check_html(str: &str) {
- if !str.contains('<') {
- panic!("{}", str)
- }
-}
-
fn get_vdom_first_element_by_class_name<'a>(dom: &'a VDom, name: &str) -> Option<&'a Node<'a>> {
let handle = dom.get_elements_by_class_name(name).next()?;
handle.get(dom.parser())
@@ -71,7 +64,7 @@ where
fn parse_marshal_inplace(env: &mut JNIEnv, str: JByteBuffer, limit: jint, mut f: F) -> i32
where
- F: FnMut(&VDom, &Parser, &str) -> Option + UnwindSafe,
+ F: FnMut(&VDom, &Parser, &str) -> Result,
R: Serialize,
{
let ptr = env.get_direct_buffer_address(&str).unwrap();
@@ -79,36 +72,31 @@ where
let buff = slice_from_raw_parts(ptr, limit as usize);
from_utf8_unchecked(&*buff)
};
- let f = move || {
- let dom = tl::parse(html, tl::ParserOptions::default()).unwrap();
+ let mut f = || {
+ let dom = tl::parse(html, tl::ParserOptions::default()).map_err(|_| html)?;
let parser = dom.parser();
- let result = f(&dom, parser, html);
- match result {
- // Nothing to marshal
- None => 0,
- Some(value) => {
- let mut cursor = unsafe {
- let slice = slice_from_raw_parts_mut(ptr, 0x80000);
- Cursor::new(&mut *slice)
- };
- serde_cbor::to_writer(&mut cursor, &value).unwrap();
- cursor.position() as i32
- }
- }
+ f(&dom, parser, html)
};
- match catch_unwind(f) {
- Ok(result) => result,
+ match f() {
+ // Nothing to marshal
Err(err) => {
- let msg = match err.downcast_ref::<&'static str>() {
- Some(s) => *s,
- None => match err.downcast_ref::() {
- Some(s) => &s[..],
- None => "Box",
- },
- };
- env.throw_new("java/lang/RuntimeException", msg).unwrap();
+ env.throw_new("java/lang/RuntimeException", err).ok();
0
}
+ Ok(value) => {
+ let mut cursor = unsafe {
+ let slice = slice_from_raw_parts_mut(ptr, 0x80000);
+ Cursor::new(&mut *slice)
+ };
+ match serde_cbor::to_writer(&mut cursor, &value) {
+ Ok(_) => cursor.position() as i32,
+ Err(err) => {
+ env.throw_new("java/lang/RuntimeException", format!("{}", err))
+ .ok();
+ 0
+ }
+ }
+ }
}
}
diff --git a/app/src/main/rust/src/parser/fav.rs b/app/src/main/rust/src/parser/fav.rs
index 29697e431..b155f5110 100644
--- a/app/src/main/rust/src/parser/fav.rs
+++ b/app/src/main/rust/src/parser/fav.rs
@@ -17,9 +17,9 @@ struct FavResult {
galleryListResult: GalleryListResult,
}
-fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Option {
+fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result {
if html.contains("This page requires you to log on.
") {
- panic!("Not logged in!")
+ return Err("Not logged in!");
}
let vec: Vec<(String, i32)> = dom
.get_elements_by_class_name("fp")
@@ -43,13 +43,13 @@ fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Option {
if vec.len() == 10 {
let list = parse_info_list(dom, parser, html)?;
let cat = vec.iter().cloned().unzip();
- Some(FavResult {
+ Ok(FavResult {
catArray: cat.0,
countArray: cat.1,
galleryListResult: list,
})
} else {
- None
+ Err("Illegal fav cat count!")
}
}
diff --git a/app/src/main/rust/src/parser/home.rs b/app/src/main/rust/src/parser/home.rs
index d211c85c3..93f0063bb 100644
--- a/app/src/main/rust/src/parser/home.rs
+++ b/app/src/main/rust/src/parser/home.rs
@@ -1,12 +1,11 @@
-use get_vdom_first_element_by_class_name;
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
use jni_fn::jni_fn;
-use parse_marshal_inplace;
use serde::Serialize;
use tl::Parser;
use tl::VDom;
+use {get_vdom_first_element_by_class_name, parse_marshal_inplace};
#[allow(non_snake_case)]
#[derive(Serialize)]
@@ -35,6 +34,6 @@ fn parse_limit(dom: &VDom, parser: &Parser) -> Option {
#[jni_fn("com.hippo.ehviewer.client.parser.HomeParserKt")]
pub fn parseLimit(mut env: JNIEnv, _class: JClass, input: JByteBuffer, limit: jint) -> jint {
parse_marshal_inplace(&mut env, input, limit, |dom, parser, _| {
- parse_limit(dom, parser)
+ parse_limit(dom, parser).ok_or("Can't parse Limit")
})
}
diff --git a/app/src/main/rust/src/parser/list.rs b/app/src/main/rust/src/parser/list.rs
index c7f0da9fe..c73da0cad 100644
--- a/app/src/main/rust/src/parser/list.rs
+++ b/app/src/main/rust/src/parser/list.rs
@@ -1,4 +1,3 @@
-use check_html;
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
@@ -101,7 +100,7 @@ fn parse_uploader_and_pages(str: &str) -> (Option, bool, i32) {
.map(|grp| grp[1].to_string());
let pages = match regex!(r"(\d+) pages
").captures(str) {
None => 0,
- Some(grp) => grp[1].parse().unwrap(),
+ Some(grp) => grp[1].parse().unwrap_or(0),
};
(uploader, str.contains("style=\"opacity:0.5\""), pages)
}
@@ -109,7 +108,7 @@ fn parse_uploader_and_pages(str: &str) -> (Option, bool, i32) {
fn parse_thumb_resolution(str: &str) -> (i32, i32) {
match regex!(r"height:(\d+)px;width:(\d+)px").captures(str) {
None => (0, 0),
- Some(grp) => (grp[1].parse().unwrap(), grp[2].parse().unwrap()),
+ Some(grp) => (grp[1].parse().unwrap_or(0), grp[2].parse().unwrap_or(0)),
}
}
@@ -129,7 +128,7 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option {
let (thumb, (thumb_height, thumb_width)) =
match tag.query_selector(parser, "[data-src]")?.next() {
None => match tag.query_selector(parser, "[src]")?.next() {
- None => panic!("No thumb found"),
+ None => return None,
Some(thumb) => (
get_node_handle_attr(&thumb, parser, "src")?,
parse_thumb_resolution(get_node_handle_attr(&thumb, parser, "style")?),
@@ -190,43 +189,52 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option {
})
}
-pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Option {
- check_html(str);
+pub fn parse_info_list(
+ dom: &VDom,
+ parser: &Parser,
+ str: &str,
+) -> Result {
+ if !str.contains('<') {
+ return Err("No content!");
+ }
if str.contains("You do not have any watched tags") {
- panic!("No watched tags!")
+ return Err("No watched tags!");
}
if str.contains("No hits found
") || str.contains("No unfiltered results found") {
- panic!("No hits found!")
+ return Err("No hits found!");
}
- let itg = get_vdom_first_element_by_class_name(dom, "itg")?;
- let children = itg.children()?;
- let iter = children.top().iter();
- let info: Vec = iter
- .filter_map(|x| parse_gallery_info(x.get(parser)?, parser))
- .collect();
- let prev = dom.get_element_by_id("uprev").and_then(|e| {
- let str = get_node_handle_attr(&e, parser, "href")?;
- Some(
- regex!("prev=(\\d+(-\\d+)?)")
- .captures(str)?
- .index(1)
- .to_string(),
- )
- });
- let next = dom.get_element_by_id("unext").and_then(|e| {
- let str = get_node_handle_attr(&e, parser, "href")?;
- Some(
- regex!("next=(\\d+(-\\d+)?)")
- .captures(str)?
- .index(1)
- .to_string(),
- )
- });
- (!info.is_empty()).then_some(GalleryListResult {
- prev,
- next,
- galleryInfoList: info,
- })
+ let f = || {
+ let itg = get_vdom_first_element_by_class_name(dom, "itg")?;
+ let children = itg.children()?;
+ let iter = children.top().iter();
+ let info: Vec = iter
+ .filter_map(|x| parse_gallery_info(x.get(parser)?, parser))
+ .collect();
+ let prev = dom.get_element_by_id("uprev").and_then(|e| {
+ let str = get_node_handle_attr(&e, parser, "href")?;
+ Some(
+ regex!("prev=(\\d+(-\\d+)?)")
+ .captures(str)?
+ .index(1)
+ .to_string(),
+ )
+ });
+ let next = dom.get_element_by_id("unext").and_then(|e| {
+ let str = get_node_handle_attr(&e, parser, "href")?;
+ Some(
+ regex!("next=(\\d+(-\\d+)?)")
+ .captures(str)?
+ .index(1)
+ .to_string(),
+ )
+ });
+ (!info.is_empty()).then_some(GalleryListResult {
+ prev,
+ next,
+ galleryInfoList: info,
+ })
+ };
+ f().ok_or("No content")
}
#[no_mangle]
diff --git a/app/src/main/rust/src/parser/torrent.rs b/app/src/main/rust/src/parser/torrent.rs
index 6f1417684..125117720 100644
--- a/app/src/main/rust/src/parser/torrent.rs
+++ b/app/src/main/rust/src/parser/torrent.rs
@@ -18,13 +18,13 @@ struct Torrent {
name: String,
}
-fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Option> {
- let list = dom.query_selector("table")?.filter_map(|e| {
+fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result, &'static str> {
+ let list = dom.query_selector("table").ok_or("No Table")?.filter_map(|e| {
let html = e.get(parser)?.inner_html(parser);
if html.contains("Expunged") {
None
} else {
- let grp = regex!(" ([0-9-]+) [0-9:]+[\\s\\S]+ ([0-9.]+ [KMGT]iB)[\\s\\S]+ ([0-9]+)[\\s\\S]+ ([0-9]+)[\\s\\S]+ ([0-9]+)[\\s\\S]+([^<]+)[\\s\\S]+onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)").captures(&html).unwrap();
+ let grp = regex!(" ([0-9-]+) [0-9:]+[\\s\\S]+ ([0-9.]+ [KMGT]iB)[\\s\\S]+ ([0-9]+)[\\s\\S]+ ([0-9]+)[\\s\\S]+ ([0-9]+)[\\s\\S]+([^<]+)[\\s\\S]+onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)").captures(&html)?;
let name = unescape(&grp[8]).ok()?;
Some(Torrent {
posted: grp[1].to_string(),
@@ -37,7 +37,7 @@ fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Option> {
})
}
}).collect::>();
- Some(list)
+ Ok(list)
}
#[no_mangle]