Don't unwind (#574)

* Don't unwind

* Fixes

* Abort in panic

* Refine

---------

Co-authored-by: GG Bond <whatever@tagkong.com>
This commit is contained in:
Vladimir DostoyevskiyandGG Bond authored and GitHub committed 2023-12-31 09:39:29 +00:00
1 parent ba53d01fa1
commit 3ea6c82a6d
6 files changed
+77 -82

No files matched your search

+1 -1
View File
@@ -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
+21 -33
View File
@@ -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<F, R>(env: &mut JNIEnv, str: JByteBuffer, limit: jint, mut f: F) -> i32
where
F: FnMut(&VDom, &Parser, &str) -> Option<R> + UnwindSafe,
F: FnMut(&VDom, &Parser, &str) -> Result<R, &'static str>,
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::<String>() {
Some(s) => &s[..],
None => "Box<dyn Any>",
},
};
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
}
}
}
}
}
+4 -4
View File
@@ -17,9 +17,9 @@ struct FavResult {
galleryListResult: GalleryListResult,
}
fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Option<FavResult> {
fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result<FavResult, &'static str> {
if html.contains("This page requires you to log on.</p>") {
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<FavResult> {
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!")
}
}
+2 -3
View File
@@ -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<Limits> {
#[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")
})
}
+45 -37
View File
@@ -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<String>, bool, i32) {
.map(|grp| grp[1].to_string());
let pages = match regex!(r"<div>(\d+) pages</div>").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<String>, 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<BaseGalleryInfo> {
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<BaseGalleryInfo> {
})
}
pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Option<GalleryListResult> {
check_html(str);
pub fn parse_info_list(
dom: &VDom,
parser: &Parser,
str: &str,
) -> Result<GalleryListResult, &'static str> {
if !str.contains('<') {
return Err("No content!");
}
if str.contains("<p>You do not have any watched tags") {
panic!("No watched tags!")
return Err("No watched tags!");
}
if str.contains("No hits found</p>") || 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<BaseGalleryInfo> = 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<BaseGalleryInfo> = 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]
+4 -4
View File
@@ -18,13 +18,13 @@ struct Torrent {
name: String,
}
fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Option<Vec<Torrent>> {
let list = dom.query_selector("table")?.filter_map(|e| {
fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result<Vec<Torrent>, &'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!("</span> ([0-9-]+) [0-9:]+</td>[\\s\\S]+</span> ([0-9.]+ [KMGT]iB)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span>([^<]+)</td>[\\s\\S]+onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)</a>").captures(&html).unwrap();
let grp = regex!("</span> ([0-9-]+) [0-9:]+</td>[\\s\\S]+</span> ([0-9.]+ [KMGT]iB)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span> ([0-9]+)</td>[\\s\\S]+</span>([^<]+)</td>[\\s\\S]+onclick=\"document.location='([^\"]+)'[^<]+>([^<]+)</a>").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<Vec<Torrent>> {
})
}
}).collect::<Vec<Torrent>>();
Some(list)
Ok(list)
}
#[no_mangle]