Phase 7 — strawcore wrapper now bridges to Sulkta-OSS/strawcore-core

Replaces the rustypipe-backed extraction with calls into the new
NPE-port crate. The UniFFI surface Kotlin sees is unchanged:

  suspend fun search(query: String): List<SearchItem>
  suspend fun streamInfo(input: String): StreamInfo
  suspend fun channelInfo(input: String): ChannelInfo
  fun initLogging()  // also wires the strawcore-core Downloader
  fun helloFromRust(name: String): String

rust/strawcore/
  * Cargo.toml      — dropped rustypipe + rquickjs-sys direct dep;
                      added strawcore-core path dep (../../../strawcore)
  * src/error.rs    — From<strawcore_core::ExtractionError>, mapping
                      ContentUnavailable variants to typed
                      StrawcoreError cases (AgeRestricted, GeoRestricted,
                      Private, RequiresLogin) instead of bucketing all
                      to Extractor
  * src/runtime.rs  — Once-guarded ReqwestDownloader init via
                      NewPipe::init_full
  * src/search.rs   — search() spawn_blocks core search_extractor::search
                      against SearchFilter::Videos
  * src/stream.rs   — stream_info() resolves URL → video_id via
                      strawcore_core::linkhandler::stream, then
                      spawn_blocks core stream_extractor::stream_info,
                      then maps StreamInfo → wrapper DTOs (combined/
                      video_only/audio_only/dash/hls)
  * src/channel.rs  — channel_info() parses input via
                      strawcore_core::linkhandler::channel (handle /
                      custom-url / legacy-user resolution lives in
                      core), then spawn_blocks core channel::channel_info

Build verified: wrapper compiles linking strawcore-core, uniffi-bindgen
generates Kotlin bindings with the same suspend fun + data class
surface Kotlin already consumes. Android NDK cross-compile + APK + on-
device smoke pending (needs build-host container).

This commits onto rollback/vc18-back-to-NPE — the existing Kotlin code
still calls NewPipeExtractor directly. Switching the Kotlin side to
consume the rust wrapper is a separate cutover.
This commit is contained in:
Sulkta 2026-05-24 17:29:23 -07:00
parent c1d7fffb1f
commit fb89b22685
7 changed files with 250 additions and 309 deletions

View file

@ -1,10 +1,12 @@
// strawcore — Rust core for the Straw Android app.
// strawcore (wrapper) — UniFFI surface for the Straw Android app.
//
// Phase U-1: hello-world smoke test. One exported function, returns a
// String so we know JNI + UniFFI marshalling works end-to-end before we
// pull in rustypipe.
//
// Phase U-2+ adds real APIs (search, stream_info, channel_info).
// Thin layer over the new Sulkta-OSS/strawcore-core crate. All extractor
// logic (InnerTube, JS deobf, stream parsing, search, channel, playlist)
// lives in core. This file:
// * re-exports the DTOs Kotlin expects under their familiar names
// * exposes #[uniffi::export] async fns that bridge Kotlin suspend funs
// to the core's blocking calls via tokio::task::spawn_blocking
// * owns init_logging() — also initializes the core Downloader
use std::sync::Once;
@ -14,18 +16,14 @@ mod runtime;
mod search;
mod stream;
#[allow(unused_imports)]
use runtime::block_on;
// Re-exports so UniFFI sees the types at the crate root for macro discovery.
pub use channel::ChannelInfo;
pub use error::StrawcoreError;
pub use search::SearchItem;
pub use stream::{AudioStreamItem, StreamInfo, VideoStreamItem};
/// Initialize Android logging once. The Kotlin side calls this from
/// StrawApp.onCreate() so anything emitted via `log::info!()` shows up in
/// `adb logcat -s strawcore`.
/// Initialize Android logging + the strawcore-core HTTP downloader.
/// Kotlin calls this from StrawApp.onCreate(). Idempotent.
#[uniffi::export]
pub fn init_logging() {
static ONCE: Once = Once::new();
@ -37,14 +35,18 @@ pub fn init_logging() {
);
log::info!("strawcore initialized");
});
runtime::ensure_initialized();
}
/// Smoke-test entry point — round-trip a string through JNI so we know
/// the bridge is working before pulling in rustypipe.
/// Smoke-test entry point — round-trip a string through JNI.
#[uniffi::export]
pub fn hello_from_rust(name: String) -> String {
log::info!("hello_from_rust called with name={}", name);
format!("hello {} from rust 🦀 (strawcore v{})", name, env!("CARGO_PKG_VERSION"))
format!(
"hello {} from rust 🦀 (strawcore v{})",
name,
env!("CARGO_PKG_VERSION")
)
}
uniffi::setup_scaffolding!();