Anyhow for parser (#788)

* Use anyhow for parser

Signed-off-by: GG Bond <whatever@tagkong.com>

* Refine

Signed-off-by: GG Bond <whatever@tagkong.com>

---------

Signed-off-by: GG Bond <whatever@tagkong.com>
Co-authored-by: GG Bond <whatever@tagkong.com>
This commit is contained in:
Vladimir DostoyevskiyandGG Bond authored and GitHub committed 2024-02-25 23:58:33 +08:00
1 parent 962f9bfff5
commit aea6fbf4ab
6 files changed
+41 -41

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ use jni_throwing;
use sha1::{Digest, Sha1};
use std::{fs::File, io::copy, os::fd::BorrowedFd};
pub fn file_sha1(mut file: File, digest: &mut [u8; 40]) -> Result<&str> {
fn file_sha1(mut file: File, digest: &mut [u8; 40]) -> Result<&str> {
let mut sha = Sha1::new();
copy(&mut file, &mut sha)?;
Ok(encode_str(&sha.finalize(), digest)?)
+26 -26
View File
@@ -15,7 +15,7 @@ extern crate sha1;
extern crate tl;
use android_logger::Config;
use anyhow::Result;
use anyhow::{anyhow, Result};
use jni::objects::JByteBuffer;
use jni::sys::{jint, jobject, JavaVM, JNI_VERSION_1_6};
use jni::JNIEnv;
@@ -25,6 +25,7 @@ use std::ffi::c_void;
use std::io::Cursor;
use std::ptr::slice_from_raw_parts_mut;
use std::str::from_utf8_unchecked;
use tl::ParserOptions;
use tl::{Bytes, Node, NodeHandle, Parser, VDom};
#[macro_export]
@@ -67,15 +68,10 @@ where
handle.get(parser)
}
fn deref_mut_direct_bytebuffer<'a>(env: &JNIEnv, buffer: JByteBuffer) -> &'a mut [u8] {
let ptr = env.get_direct_buffer_address(&buffer).unwrap();
let cap = env.get_direct_buffer_capacity(&buffer).unwrap();
unsafe { &mut *slice_from_raw_parts_mut(ptr, cap) }
}
fn throw_msg(env: &mut JNIEnv, msg: &str) -> i32 {
env.throw_new("java/lang/RuntimeException", msg).ok();
0
fn deref_mut_direct_bytebuffer(env: &JNIEnv, buffer: JByteBuffer) -> Result<&'static mut [u8]> {
let ptr = env.get_direct_buffer_address(&buffer)?;
let cap = env.get_direct_buffer_capacity(&buffer)?;
Ok(unsafe { &mut *slice_from_raw_parts_mut(ptr, cap) })
}
trait ThrowingHasDefault {
@@ -88,6 +84,12 @@ impl ThrowingHasDefault for jobject {
}
}
impl ThrowingHasDefault for i32 {
fn default() -> Self {
0
}
}
fn jni_throwing<F, R>(env: &mut JNIEnv, f: F) -> R
where
F: FnOnce(&mut JNIEnv) -> Result<R>,
@@ -96,7 +98,8 @@ where
match f(env) {
Ok(value) => value,
Err(err) => {
throw_msg(env, &format!("{err}"));
let msg = format!("{err}");
env.throw_new("java/lang/RuntimeException", msg).ok();
R::default()
}
}
@@ -104,23 +107,20 @@ where
fn parse_marshal_inplace<F, R>(env: &mut JNIEnv, str: JByteBuffer, limit: jint, f: F) -> i32
where
F: Fn(&VDom, &str) -> Result<R, &'static str>,
F: Fn(&VDom, &str) -> Result<R>,
R: Serialize,
{
let buffer = deref_mut_direct_bytebuffer(env, str);
let html = unsafe { from_utf8_unchecked(&buffer[..limit as usize]) };
let value = match tl::parse(html, tl::ParserOptions::default()) {
Ok(dom) => match f(&dom, html) {
Err(err) => return throw_msg(env, err),
Ok(value) => value,
},
Err(_) => return throw_msg(env, html),
};
let mut cursor = Cursor::new(buffer);
match serde_cbor::to_writer(&mut cursor, &value) {
Ok(_) => cursor.position() as i32,
Err(err) => throw_msg(env, &format!("{}", err)),
}
jni_throwing(env, |env| {
let buffer = deref_mut_direct_bytebuffer(env, str)?;
let value = {
let html = unsafe { from_utf8_unchecked(&buffer[..limit as usize]) };
let dom = tl::parse(html, ParserOptions::default()).map_err(|_| anyhow!("{html}"))?;
f(&dom, html)?
};
let mut cursor = Cursor::new(buffer);
serde_cbor::to_writer(&mut cursor, &value)?;
Ok(cursor.position() as i32)
})
}
fn get_node_handle_attr<'a>(
+4 -3
View File
@@ -1,3 +1,4 @@
use anyhow::{bail, Result};
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
@@ -17,9 +18,9 @@ struct FavResult {
galleryListResult: GalleryListResult,
}
fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result<FavResult, &'static str> {
fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result<FavResult> {
if html.contains("This page requires you to log on.</p>") {
return Err("Not logged in!");
bail!("Not logged in!")
}
let vec: Vec<(String, i32)> = dom
.get_elements_by_class_name("fp")
@@ -49,7 +50,7 @@ fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result<FavResult, &'sta
galleryListResult: list,
})
} else {
Err("Illegal fav cat count!")
bail!("Illegal fav cat count!")
}
}
+2 -1
View File
@@ -1,3 +1,4 @@
use anyhow::anyhow;
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
@@ -34,6 +35,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, _| {
parse_limit(dom, dom.parser()).ok_or("Can't parse Limit")
parse_limit(dom, dom.parser()).ok_or(anyhow!("Can't parse Limit"))
})
}
+5 -8
View File
@@ -1,3 +1,4 @@
use anyhow::{anyhow, bail, Result};
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
@@ -189,16 +190,12 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option<BaseGalleryInfo> {
})
}
pub fn parse_info_list(
dom: &VDom,
parser: &Parser,
str: &str,
) -> Result<GalleryListResult, &'static str> {
pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Result<GalleryListResult> {
if str.contains("<p>You do not have any watched tags") {
return Err("No watched tags!");
bail!("No watched tags!")
}
if str.contains("No hits found</p>") || str.contains("No unfiltered results found") {
return Err("No hits found!");
bail!("No hits found!")
}
let f = || {
let itg = get_vdom_first_element_by_class_name(dom, "itg")?;
@@ -231,7 +228,7 @@ pub fn parse_info_list(
galleryInfoList: info,
})
};
f().ok_or("No content")
f().ok_or(anyhow!("No content"))
}
#[no_mangle]
+3 -2
View File
@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use jni::objects::{JByteBuffer, JClass};
use jni::sys::jint;
use jni::JNIEnv;
@@ -18,8 +19,8 @@ struct Torrent {
name: String,
}
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| {
fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result<Vec<Torrent>> {
let list = dom.query_selector("table").ok_or(anyhow!("No Table"))?.filter_map(|e| {
let html = e.get(parser)?.inner_html(parser);
if html.contains("Expunged") {
None