From 45a5bae8b2f9110283ea859e2494b1e45d09f828 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:39:03 +0800 Subject: [PATCH] Group rust ffi code (#1893) * Group rust ffi code Signed-off-by: Dude so hot * Fix Signed-off-by: Dude so hot * Fix Signed-off-by: Dude so hot * Refine Signed-off-by: Dude so hot --------- Signed-off-by: Dude so hot Co-authored-by: Dude so hot --- app/src/main/cpp/CMakeLists.txt | 4 +- app/src/main/rust/Cargo.toml | 10 +- app/src/main/rust/src/ffi.rs | 3 + app/src/main/rust/src/ffi/android.rs | 55 +++++++ .../src/{img/copy_ahb.rs => ffi/android_o.rs} | 5 +- app/src/main/rust/src/ffi/jvm.rs | 143 ++++++++++++++++++ app/src/main/rust/src/img.rs | 5 +- app/src/main/rust/src/img/border.rs | 21 +-- app/src/main/rust/src/img/qr_code.rs | 17 +-- app/src/main/rust/src/lib.rs | 114 +------------- app/src/main/rust/src/parser.rs | 10 +- app/src/main/rust/src/parser/config.rs | 23 +-- app/src/main/rust/src/parser/fav.rs | 20 +-- app/src/main/rust/src/parser/home.rs | 21 +-- app/src/main/rust/src/parser/list.rs | 16 +- app/src/main/rust/src/parser/torrent.rs | 20 +-- 16 files changed, 246 insertions(+), 241 deletions(-) create mode 100644 app/src/main/rust/src/ffi.rs create mode 100644 app/src/main/rust/src/ffi/android.rs rename app/src/main/rust/src/{img/copy_ahb.rs => ffi/android_o.rs} (92%) create mode 100644 app/src/main/rust/src/ffi/jvm.rs diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index df0a894e4..392a04320 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -111,7 +111,9 @@ FetchContent_MakeAvailable(Corrosion) corrosion_import_crate(MANIFEST_PATH ../rust/Cargo.toml LOCKED) corrosion_add_target_local_rustflags(ehviewer_rust "-Clink-args=-Wl,-z,max-page-size=16384") if (ANDROID_NATIVE_API_LEVEL GREATER_EQUAL 26) - corrosion_set_features(ehviewer_rust FEATURES api-level-26) + corrosion_set_features(ehviewer_rust FEATURES android-26) +else () + corrosion_set_features(ehviewer_rust FEATURES android) endif () # Build and link our app's native lib diff --git a/app/src/main/rust/Cargo.toml b/app/src/main/rust/Cargo.toml index 026965063..4ecf040ae 100644 --- a/app/src/main/rust/Cargo.toml +++ b/app/src/main/rust/Cargo.toml @@ -7,12 +7,14 @@ edition = "2021" crate-type = ["cdylib"] [features] -api-level-26 = ["ndk/api-level-26"] +jvm = ["dep:jni", "dep:jni_fn"] +android = ["dep:ndk", "jvm", "ndk/bitmap"] +android-26 = ["android", "ndk/api-level-26"] [dependencies] regex-lite = "0.1" -jni = "0.21" -jni_fn = "0.1" +jni = { version = "0.21", optional = true } +jni_fn = { version = "0.1", optional = true } quick-xml = { default-features = false, version = "0.37" } tl = "0.7" log = "0.4" @@ -22,7 +24,7 @@ serde = { version = "1.0", features = ["derive"] } anyhow = "1.0" image = { default-features = false, version = "0.25" } rxing = { default-features = false, version = "0.6" } -ndk = { version = "0.9", features = ["bitmap"] } +ndk = { version = "0.9", optional = true } [profile.release] panic = "abort" diff --git a/app/src/main/rust/src/ffi.rs b/app/src/main/rust/src/ffi.rs new file mode 100644 index 000000000..a0de50146 --- /dev/null +++ b/app/src/main/rust/src/ffi.rs @@ -0,0 +1,3 @@ +mod android; +mod android_o; +mod jvm; diff --git a/app/src/main/rust/src/ffi/android.rs b/app/src/main/rust/src/ffi/android.rs new file mode 100644 index 000000000..e54709ac9 --- /dev/null +++ b/app/src/main/rust/src/ffi/android.rs @@ -0,0 +1,55 @@ +#![cfg(feature = "android")] + +use super::jvm::jni_throwing; +use crate::img::border::detect_border; +use crate::img::qr_code::detect_image_ad; +use anyhow::{Context, Result}; +use image::{ImageBuffer, Rgba}; +use jni::objects::JClass; +use jni::sys::jboolean; +use jni::sys::{jintArray, jobject}; +use jni::JNIEnv; +use jni_fn::jni_fn; +use ndk::bitmap::Bitmap; +use std::ptr::slice_from_raw_parts; + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.image.ImageKt")] +pub fn detectBorder(mut env: JNIEnv, _class: JClass, object: jobject) -> jintArray { + jni_throwing(&mut env, |env| { + let slice = with_bitmap_content(env, object, |img| Ok(detect_border(&img)))?; + let array = env.new_int_array(4)?; + env.set_int_array_region(&array, 0, &slice.context("Image too small!")?)?; + Ok(array.into_raw()) + }) +} + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.image.ImageKt")] +pub fn hasQrCode(mut env: JNIEnv, _class: JClass, object: jobject) -> jboolean { + jni_throwing(&mut env, |env| { + with_bitmap_content(env, object, |image| Ok(detect_image_ad(image) as jboolean)) + }) +} + +pub fn with_bitmap_content(env: &mut JNIEnv, bitmap: jobject, f: F) -> Result +where + F: FnOnce(ImageBuffer, &[u8]>) -> Result, +{ + // SAFETY: kotlin caller must ensure bitmap is valid. + let handle = unsafe { Bitmap::from_jni(env.get_raw(), bitmap) }; + + let info = handle.info()?; + let (width, height) = (info.width(), info.height()); + let ptr = handle.lock_pixels()? as *const u8; + + // SAFETY: maybe unsafe if bitmap buffer not RGBA8888 format. + let buffer = unsafe { &*slice_from_raw_parts(ptr, (width * height * 4) as usize) }; + + let image = ImageBuffer::from_raw(width, height, buffer); + let result = image.context("Image buffer not RGBA8888!!!").and_then(f); + handle.unlock_pixels()?; + result +} diff --git a/app/src/main/rust/src/img/copy_ahb.rs b/app/src/main/rust/src/ffi/android_o.rs similarity index 92% rename from app/src/main/rust/src/img/copy_ahb.rs rename to app/src/main/rust/src/ffi/android_o.rs index 9b85f0c48..4ab3dee2a 100644 --- a/app/src/main/rust/src/img/copy_ahb.rs +++ b/app/src/main/rust/src/ffi/android_o.rs @@ -1,6 +1,7 @@ -#![cfg(feature = "api-level-26")] +#![cfg(feature = "android-26")] -use crate::{jni_throwing, with_bitmap_content}; +use super::android::with_bitmap_content; +use super::jvm::jni_throwing; use anyhow::Context; use image::{GenericImage, GenericImageView, ImageBuffer}; use jni::objects::JClass; diff --git a/app/src/main/rust/src/ffi/jvm.rs b/app/src/main/rust/src/ffi/jvm.rs new file mode 100644 index 000000000..b7193a90b --- /dev/null +++ b/app/src/main/rust/src/ffi/jvm.rs @@ -0,0 +1,143 @@ +#![cfg(feature = "jvm")] + +use crate::parser::config::parse_fav_cat; +use crate::parser::fav::parse_fav; +use crate::parser::home::parse_limit; +use crate::parser::list::parse_info_list; +use crate::parser::torrent::parse_torrent_list; +use crate::EhError; +use android_logger::Config; +use anyhow::{ensure, Context, Result}; +use jni::objects::{JByteBuffer, JClass}; +use jni::sys::{jboolean, jint, jobject, JNI_VERSION_1_6}; +use jni::{JNIEnv, JavaVM}; +use jni_fn::jni_fn; +use log::LevelFilter; +use serde::Serialize; +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, VDom}; + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.client.parser.FavoritesParserKt")] +pub fn parseFav(mut env: JNIEnv, _class: JClass, input: JByteBuffer, limit: jint) -> jint { + parse_marshal_inplace(&mut env, input, limit, |dom, html| { + parse_fav(dom, dom.parser(), html) + }) +} + +#[no_mangle] +#[allow(non_snake_case)] +#[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()).context("Can't parse Limit") + }) +} + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.client.parser.GalleryListParserKt")] +pub fn parseGalleryInfoList(mut env: JNIEnv, _: JClass, buffer: JByteBuffer, limit: jint) -> jint { + parse_marshal_inplace(&mut env, buffer, limit, |dom, str| { + parse_info_list(dom, dom.parser(), str) + }) +} + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.client.parser.TorrentParserKt")] +pub fn parseTorrent(mut env: JNIEnv, _class: JClass, buffer: JByteBuffer, limit: jint) -> jint { + parse_marshal_inplace(&mut env, buffer, limit, |dom, _| { + parse_torrent_list(dom, dom.parser()) + }) +} + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.client.parser.UserConfigParser")] +pub fn parseFavCat(mut env: JNIEnv, _class: JClass, buffer: JByteBuffer, limit: jint) -> jint { + parse_marshal_inplace(&mut env, buffer, limit, |_, body| Ok(parse_fav_cat(body))) +} + +fn deref_mut_direct_bytebuffer<'local>( + env: &JNIEnv, + buffer: JByteBuffer<'local>, +) -> Result<&'local mut [u8]> { + let ptr = env.get_direct_buffer_address(&buffer)?; + let cap = env.get_direct_buffer_capacity(&buffer)?; + + // SAFETY: jni contract, buffer must alive through native call. + Ok(unsafe { &mut *slice_from_raw_parts_mut(ptr, cap) }) +} + +pub trait ThrowingHasDefault { + fn default() -> Self; +} + +impl ThrowingHasDefault for jboolean { + fn default() -> Self { + 0 as jboolean + } +} + +impl ThrowingHasDefault for jobject { + fn default() -> Self { + 0 as jobject + } +} + +impl ThrowingHasDefault for i32 { + fn default() -> Self { + 0 + } +} + +impl ThrowingHasDefault for () { + fn default() -> Self {} +} + +pub fn jni_throwing(env: &mut JNIEnv, f: F) -> R +where + F: FnOnce(&mut JNIEnv) -> Result, + R: ThrowingHasDefault, +{ + match f(env) { + Ok(value) => value, + Err(err) => { + let msg = format!("{err}"); + env.throw_new("java/lang/RuntimeException", msg).ok(); + R::default() + } + } +} + +pub fn parse_marshal_inplace(env: &mut JNIEnv, str: JByteBuffer, limit: jint, f: F) -> i32 +where + F: Fn(&VDom, &str) -> Result, + R: Serialize, +{ + jni_throwing(env, |env| { + let buffer = deref_mut_direct_bytebuffer(env, str)?; + let value = { + // SAFETY: ktor client ensure html content is valid utf-8. + let html = unsafe { from_utf8_unchecked(&buffer[..limit as usize]) }; + + let dom = tl::parse(html, ParserOptions::default())?; + ensure!(dom.version().is_some(), EhError::Error(html.to_string())); + f(&dom, html)? + }; + let mut cursor = Cursor::new(buffer); + serde_cbor::to_writer(&mut cursor, &value)?; + Ok(cursor.position() as i32) + }) +} + +#[no_mangle] +pub extern "system" fn JNI_OnLoad(_: JavaVM, _: *mut c_void) -> jint { + android_logger::init_once(Config::default().with_max_level(LevelFilter::Debug)); + JNI_VERSION_1_6 +} diff --git a/app/src/main/rust/src/img.rs b/app/src/main/rust/src/img.rs index aca9e08ae..9a2fb15ea 100644 --- a/app/src/main/rust/src/img.rs +++ b/app/src/main/rust/src/img.rs @@ -1,3 +1,2 @@ -mod border; -mod copy_ahb; -mod qr_code; +pub mod border; +pub mod qr_code; diff --git a/app/src/main/rust/src/img/border.rs b/app/src/main/rust/src/img/border.rs index a7e7fbb35..8e0ad68c1 100644 --- a/app/src/main/rust/src/img/border.rs +++ b/app/src/main/rust/src/img/border.rs @@ -1,10 +1,4 @@ -use crate::{jni_throwing, with_bitmap_content}; -use anyhow::Context; use image::{ImageBuffer, Luma, Pixel, Rgba}; -use jni::objects::JClass; -use jni::sys::{jintArray, jobject}; -use jni::JNIEnv; -use jni_fn::jni_fn; /** A line will be considered as having content if 0.25% of it is filled. */ static FILLED_RATIO_LIMIT: f32 = 0.0025; @@ -72,7 +66,8 @@ fn detect_border_lines<'pixel>( } } -fn detect_border(image: &ImageBuffer, &[u8]>) -> Option<[i32; 4]> { +#[allow(dead_code)] +pub fn detect_border(image: &ImageBuffer, &[u8]>) -> Option<[i32; 4]> { let (w, h) = image.dimensions(); let top = detect_border_lines(image.rows(), w); let bottom = detect_border_lines(image.rows().rev(), w); @@ -81,15 +76,3 @@ fn detect_border(image: &ImageBuffer, &[u8]>) -> Option<[i32; 4]> { let right = detect_border_lines(iter.rev(), h); Some([left, top, w as i32 - right, h as i32 - bottom]) } - -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.image.ImageKt")] -pub fn detectBorder(mut env: JNIEnv, _class: JClass, object: jobject) -> jintArray { - jni_throwing(&mut env, |env| { - let slice = with_bitmap_content(env, object, |img| Ok(detect_border(&img)))?; - let array = env.new_int_array(4)?; - env.set_int_array_region(&array, 0, &slice.context("Image too small!")?)?; - Ok(array.into_raw()) - }) -} diff --git a/app/src/main/rust/src/img/qr_code.rs b/app/src/main/rust/src/img/qr_code.rs index e23c3b108..1e2e324ed 100644 --- a/app/src/main/rust/src/img/qr_code.rs +++ b/app/src/main/rust/src/img/qr_code.rs @@ -1,16 +1,12 @@ -use crate::{jni_throwing, with_bitmap_content}; use image::{ImageBuffer, Rgba}; -use jni::objects::JClass; -use jni::sys::{jboolean, jobject}; -use jni::JNIEnv; -use jni_fn::jni_fn; use rxing::common::HybridBinarizer; use rxing::qrcode::detector::FinderPatternFinder; use rxing::{BinaryBitmap, DecodingHintDictionary, Point, RGBLuminanceSource}; use std::f32::consts::FRAC_1_SQRT_2; use std::ptr::slice_from_raw_parts; -fn detect_image_ad(image: ImageBuffer, &[u8]>) -> bool { +#[allow(dead_code)] +pub fn detect_image_ad(image: ImageBuffer, &[u8]>) -> bool { let (width, height) = (image.width() as usize, image.height() as usize); let buffer = image.into_raw(); let pixels = unsafe { &*slice_from_raw_parts(buffer.as_ptr() as *const u32, buffer.len()) }; @@ -30,12 +26,3 @@ fn detect_image_ad(image: ImageBuffer, &[u8]>) -> bool { Err(_) => false, } } - -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.image.ImageKt")] -pub fn hasQrCode(mut env: JNIEnv, _class: JClass, object: jobject) -> jboolean { - jni_throwing(&mut env, |env| { - with_bitmap_content(env, object, |image| Ok(detect_image_ad(image) as jboolean)) - }) -} diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs index f800314a1..98d56e621 100644 --- a/app/src/main/rust/src/lib.rs +++ b/app/src/main/rust/src/lib.rs @@ -1,21 +1,8 @@ +mod ffi; mod img; mod parser; -use android_logger::Config; -use anyhow::{ensure, Context, Result}; -use image::{ImageBuffer, Rgba}; -use jni::objects::JByteBuffer; -use jni::sys::{jboolean, jint, jobject, JavaVM, JNI_VERSION_1_6}; -use jni::JNIEnv; -use log::LevelFilter; -use ndk::bitmap::Bitmap; -use serde::Serialize; -use std::ffi::c_void; use std::fmt::{Debug, Display, Formatter}; -use std::io::Cursor; -use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut}; -use std::str::from_utf8_unchecked; -use tl::ParserOptions; use tl::{Bytes, Node, NodeHandle, Parser, VDom}; #[macro_export] @@ -58,43 +45,6 @@ where handle.get(parser) } -fn deref_mut_direct_bytebuffer<'local>( - env: &JNIEnv, - buffer: JByteBuffer<'local>, -) -> Result<&'local mut [u8]> { - let ptr = env.get_direct_buffer_address(&buffer)?; - let cap = env.get_direct_buffer_capacity(&buffer)?; - - // SAFETY: jni contract, buffer must alive through native call. - Ok(unsafe { &mut *slice_from_raw_parts_mut(ptr, cap) }) -} - -trait ThrowingHasDefault { - fn default() -> Self; -} - -impl ThrowingHasDefault for jboolean { - fn default() -> Self { - 0 as jboolean - } -} - -impl ThrowingHasDefault for jobject { - fn default() -> Self { - 0 as jobject - } -} - -impl ThrowingHasDefault for i32 { - fn default() -> Self { - 0 - } -} - -impl ThrowingHasDefault for () { - fn default() -> Self {} -} - #[derive(Debug)] enum EhError { NoHits, @@ -115,42 +65,6 @@ impl Display for EhError { } } -fn jni_throwing(env: &mut JNIEnv, f: F) -> R -where - F: FnOnce(&mut JNIEnv) -> Result, - R: ThrowingHasDefault, -{ - match f(env) { - Ok(value) => value, - Err(err) => { - let msg = format!("{err}"); - env.throw_new("java/lang/RuntimeException", msg).ok(); - R::default() - } - } -} - -fn parse_marshal_inplace(env: &mut JNIEnv, str: JByteBuffer, limit: jint, f: F) -> i32 -where - F: Fn(&VDom, &str) -> Result, - R: Serialize, -{ - jni_throwing(env, |env| { - let buffer = deref_mut_direct_bytebuffer(env, str)?; - let value = { - // SAFETY: ktor client ensure html content is valid utf-8. - let html = unsafe { from_utf8_unchecked(&buffer[..limit as usize]) }; - - let dom = tl::parse(html, ParserOptions::default())?; - ensure!(dom.version().is_some(), EhError::Error(html.to_string())); - 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>( node: &NodeHandle, parser: &'a Parser, @@ -173,29 +87,3 @@ fn query_childs_first_match_attr<'a>( let mut iter = node.as_tag()?.query_selector(parser, &selector)?; get_node_handle_attr(&iter.next()?, parser, attr) } - -fn with_bitmap_content(env: &mut JNIEnv, bitmap: jobject, f: F) -> Result -where - F: FnOnce(ImageBuffer, &[u8]>) -> Result, -{ - // SAFETY: kotlin caller must ensure bitmap is valid. - let handle = unsafe { Bitmap::from_jni(env.get_raw(), bitmap) }; - - let info = handle.info()?; - let (width, height) = (info.width(), info.height()); - let ptr = handle.lock_pixels()? as *const u8; - - // SAFETY: maybe unsafe if bitmap buffer not RGBA8888 format. - let buffer = unsafe { &*slice_from_raw_parts(ptr, (width * height * 4) as usize) }; - - let image = ImageBuffer::from_raw(width, height, buffer); - let result = image.context("Image buffer not RGBA8888!!!").and_then(f); - handle.unlock_pixels()?; - result -} - -#[no_mangle] -pub extern "system" fn JNI_OnLoad(_: JavaVM, _: *mut c_void) -> jint { - android_logger::init_once(Config::default().with_max_level(LevelFilter::Debug)); - JNI_VERSION_1_6 -} diff --git a/app/src/main/rust/src/parser.rs b/app/src/main/rust/src/parser.rs index b1188dc1d..05fb27d87 100644 --- a/app/src/main/rust/src/parser.rs +++ b/app/src/main/rust/src/parser.rs @@ -1,5 +1,5 @@ -mod config; -mod fav; -mod home; -mod list; -mod torrent; +pub mod config; +pub mod fav; +pub mod home; +pub mod list; +pub mod torrent; diff --git a/app/src/main/rust/src/parser/config.rs b/app/src/main/rust/src/parser/config.rs index 640c1454f..a2118ad5b 100644 --- a/app/src/main/rust/src/parser/config.rs +++ b/app/src/main/rust/src/parser/config.rs @@ -1,19 +1,10 @@ -use crate::{parse_marshal_inplace, regex}; -use jni::objects::{JByteBuffer, JClass}; -use jni::sys::jint; -use jni::JNIEnv; -use jni_fn::jni_fn; +use crate::regex; use quick_xml::escape::unescape; -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.client.parser.UserConfigParser")] -pub fn parseFavCat(mut env: JNIEnv, _class: JClass, buffer: JByteBuffer, limit: jint) -> jint { - parse_marshal_inplace(&mut env, buffer, limit, |_, body| { - let cat = regex!(">(); - Ok(cat) - }) +#[allow(dead_code)] +pub fn parse_fav_cat(html: &str) -> Vec { + regex!(", countArray: Vec, galleryListResult: GalleryListResult, } -fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result { +#[allow(dead_code)] +pub fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result { if html.contains("This page requires you to log on.

") { bail!(EhError::NeedLogin) } @@ -53,12 +50,3 @@ fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result { bail!("Illegal fav cat count!") } } - -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.client.parser.FavoritesParserKt")] -pub fn parseFav(mut env: JNIEnv, _class: JClass, input: JByteBuffer, limit: jint) -> jint { - parse_marshal_inplace(&mut env, input, limit, |dom, html| { - parse_fav(dom, dom.parser(), html) - }) -} diff --git a/app/src/main/rust/src/parser/home.rs b/app/src/main/rust/src/parser/home.rs index 568782726..ff2d41e43 100644 --- a/app/src/main/rust/src/parser/home.rs +++ b/app/src/main/rust/src/parser/home.rs @@ -1,22 +1,18 @@ -use crate::{get_vdom_first_element_by_class_name, parse_marshal_inplace}; -use anyhow::Context; -use jni::objects::{JByteBuffer, JClass}; -use jni::sys::jint; -use jni::JNIEnv; -use jni_fn::jni_fn; +use crate::get_vdom_first_element_by_class_name; use serde::Serialize; use tl::Parser; use tl::VDom; #[allow(non_snake_case)] #[derive(Serialize)] -struct Limits { +pub struct Limits { current: i32, maximum: i32, resetCost: i32, } -fn parse_limit(dom: &VDom, parser: &Parser) -> Option { +#[allow(dead_code)] +pub fn parse_limit(dom: &VDom, parser: &Parser) -> Option { let limit_box = get_vdom_first_element_by_class_name(dom, "homebox")?.as_tag()?; let vec = limit_box .query_selector(parser, "strong")? @@ -46,12 +42,3 @@ fn parse_limit(dom: &VDom, parser: &Parser) -> Option { _ => None, } } - -#[no_mangle] -#[allow(non_snake_case)] -#[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()).context("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 2da10d6e5..0af6f9282 100644 --- a/app/src/main/rust/src/parser/list.rs +++ b/app/src/main/rust/src/parser/list.rs @@ -1,13 +1,9 @@ +use crate::EhError; use crate::{get_element_by_id, get_vdom_first_element_by_class_name}; use crate::{get_first_element_by_class_name, query_childs_first_match_attr}; use crate::{get_node_attr, get_node_handle_attr, regex}; -use crate::{parse_marshal_inplace, EhError}; use crate::{EHGT_PREFIX, EX_PREFIX}; use anyhow::{bail, Context, Result}; -use jni::objects::{JByteBuffer, JClass}; -use jni::sys::jint; -use jni::JNIEnv; -use jni_fn::jni_fn; use quick_xml::escape::unescape; use serde::Serialize; use std::borrow::Cow; @@ -197,6 +193,7 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option { }) } +#[allow(dead_code)] pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Result { if str.contains("

You do not have any watched tags") { bail!(EhError::NoWatched) @@ -241,12 +238,3 @@ pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Result jint { - parse_marshal_inplace(&mut env, buffer, limit, |dom, str| { - parse_info_list(dom, dom.parser(), str) - }) -} diff --git a/app/src/main/rust/src/parser/torrent.rs b/app/src/main/rust/src/parser/torrent.rs index 76beb57e7..d69849e50 100644 --- a/app/src/main/rust/src/parser/torrent.rs +++ b/app/src/main/rust/src/parser/torrent.rs @@ -1,15 +1,11 @@ -use crate::{parse_marshal_inplace, regex}; +use crate::regex; use anyhow::{Context, Result}; -use jni::objects::{JByteBuffer, JClass}; -use jni::sys::jint; -use jni::JNIEnv; -use jni_fn::jni_fn; use quick_xml::escape::unescape; use serde::Serialize; use tl::{Parser, VDom}; #[derive(Serialize)] -struct Torrent { +pub struct Torrent { outdated: bool, posted: String, size: String, @@ -21,7 +17,8 @@ struct Torrent { name: String, } -fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result> { +#[allow(dead_code)] +pub fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result> { let list = dom.query_selector("table").context("No Table")?.filter_map(|e| { let html = e.get(parser)?.inner_html(parser); if html.contains("Expunged") { @@ -44,12 +41,3 @@ fn parse_torrent_list(dom: &VDom, parser: &Parser) -> Result> { }).collect::>(); Ok(list) } - -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.client.parser.TorrentParserKt")] -pub fn parseTorrent(mut env: JNIEnv, _class: JClass, buffer: JByteBuffer, limit: jint) -> jint { - parse_marshal_inplace(&mut env, buffer, limit, |dom, _| { - parse_torrent_list(dom, dom.parser()) - }) -}