straw/rust
Cobb 990e328d13 strawcore wrapper: a stream's live-now flag and the feed's no-views-yet mark
StreamInfo gains is_live: true when the core read the player response's
isLive (its stream type is then VideoLiveStream), false for an ordinary
video and for a stream that has just ended. On 2026-10-24 (UTC) the core's
stream lookup gave VideoLiveStream for 3 of 3 live videos tried and
VideoStream for the one regular video tried. The app carries it as
ResolvedPlayback.live; the play queue uses it in a later commit.

SearchItem gains no_views_yet, set only from a channel's RSS feed when
its <media:statistics views="0"/> says no views. In 160 channel feeds
captured on 2026-10-22, all 2,184 entries carried that element and 8
had zero views; looked up on 2026-10-24, 4 of the 8 were upcoming
streams and 4 ordinary uploads (2 of them Shorts) published 3 minutes
to 46 hours before the capture. The count itself is still not shown.
StreamItem carries the mark as noViewsYet; the feed uses it in a later
commit.

A test pins that an RSS entry never carries a live state: the feed
overlays the lookup's live state only on an item whose own is None, so
an RSS entry marked live could never lose the mark. Before, marking
every RSS entry live passed every test.
2026-10-23 20:28:08 -07:00
..
strawcore strawcore wrapper: a stream's live-now flag and the feed's no-views-yet mark 2026-10-23 20:28:08 -07:00
Cargo.lock diag: expand dogfood logging — lighter scrub + always-log failures + wrapper catch-all 2026-08-06 08:17:15 -07:00
Cargo.toml speed(wrapper): opt-level=2 for the JS-interpreter crates (S5) 2026-07-29 08:25:47 -07:00
README.md Public-flip audit: scrub audit-ticket prefixes + internal references + tighten README 2026-05-27 13:29:53 -07:00

rust/ — strawcore: Rust YouTube core for Straw

Phase U- of the Straw build. Goal: replace the Java NewPipeExtractor dependency with a Rust core (rustypipe + tokio + reqwest), exposed to the Kotlin/Compose UI via UniFFI. Compose UI stays in Kotlin — only the YouTube/Innertube fetching layer moves to Rust.

Phases

Phase What
U-1 Toolchain + UniFFI smoke test (hello_from_rust) round-tripping through JNA. No real APIs yet.
U-2 rustypipe search. SearchViewModel calls the Rust core.
U-3 rustypipe streamInfo + streams. VideoDetailViewModel + PlayerViewModel use it.
U-4 rustypipe channel + tabs. ChannelViewModel + SubscriptionFeedViewModel.
U-5 Rip NewPipeExtractor Java dep. Measure APK + cold-fetch latency before/after.
U-6 (stretch) SponsorBlock + RYD HTTP through reqwest + tokio in the same lib.

Build chain

Build container (Sulkta uses one; any toolchain matching this layout works)
├── rustup stable (target add: aarch64-linux-android, armv7-linux-androideabi,
│                  x86_64-linux-android, i686-linux-android)
├── cargo-ndk      (cross-compile helper)
├── android-sdk    (ANDROID_HOME, sdkmanager, build-tools, platforms)
└── android-ndk    (ANDROID_NDK_HOME, r27c LTS)

Gradle (strawApp/build.gradle.kts)
├── cargoBuild         Exec task → cargo ndk -t <abi>... -o jniLibs/ build --release
├── uniffiBindgen      Exec task → cargo run --bin uniffi-bindgen ... --library libstrawcore.so
└── source-set wiring  generated Kotlin lands in strawApp/src/main/java/uniffi/strawcore/

Runtime (StrawApp.onCreate)
├── System.loadLibrary("strawcore")
└── uniffi.strawcore.initLogging()

Why UniFFI (and not raw JNI / JNA bindings)

  • Hand-written JNI: tedious, error-prone, every type change is two files (Kotlin + Rust) that must stay in sync.
  • Raw JNA: better, but you still hand-write the Kotlin side and worry about string ownership.
  • UniFFI: write Rust, annotate with #[uniffi::export], get a Kotlin shim generated. Strings, structs, enums, Result types, async functions all cross the boundary transparently. The runtime is JNA under the hood.

When in doubt

  • cargo check -p strawcore --target aarch64-linux-android — fast iteration.
  • cargo run --bin uniffi-bindgen -- generate ... — regenerate Kotlin bindings.
  • adb logcat -s strawcore — Rust log::info!() lands here.
  • aapt dump badging strawApp/build/outputs/apk/debug/strawApp-debug.apk — inspect what ABIs/native-libs the APK carries.