From 249915c3bec673b8a835c21ad4d38d817098dd7a Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 14 Feb 2025 15:14:14 -0700 Subject: [PATCH] musikr: fix iostream pinning --- musikr/src/main/jni/src/jstream.rs | 2 +- musikr/src/main/jni/src/taglib/bridge.rs | 79 ++++++++++++++++++++---- musikr/src/main/jni/src/taglib/file.rs | 19 +++--- musikr/src/main/jni/src/taglib/mod.rs | 1 - musikr/src/main/jni/src/taglib/stream.rs | 61 ------------------ 5 files changed, 79 insertions(+), 83 deletions(-) delete mode 100644 musikr/src/main/jni/src/taglib/stream.rs diff --git a/musikr/src/main/jni/src/jstream.rs b/musikr/src/main/jni/src/jstream.rs index a5d033797..b9d2f1625 100644 --- a/musikr/src/main/jni/src/jstream.rs +++ b/musikr/src/main/jni/src/jstream.rs @@ -1,4 +1,4 @@ -use crate::taglib::stream::IOStream; +use crate::taglib::file::IOStream; use jni::objects::{JObject, JValue}; use std::io::{Read, Seek, SeekFrom, Write}; use crate::SharedEnv; diff --git a/musikr/src/main/jni/src/taglib/bridge.rs b/musikr/src/main/jni/src/taglib/bridge.rs index 33fe7fbd3..76f2266ee 100644 --- a/musikr/src/main/jni/src/taglib/bridge.rs +++ b/musikr/src/main/jni/src/taglib/bridge.rs @@ -1,20 +1,18 @@ -use super::stream::BridgeStream; - #[cxx::bridge] mod bridge_impl { // Expose Rust IOStream to C++ extern "Rust" { #[cxx_name = "BridgeStream"] - type BridgeStream<'a>; + type TIOStream<'a>; - fn name(self: &mut BridgeStream<'_>) -> String; - fn read(self: &mut BridgeStream<'_>, buffer: &mut [u8]) -> usize; - fn write(self: &mut BridgeStream<'_>, data: &[u8]); - fn seek(self: &mut BridgeStream<'_>, offset: i64, whence: i32); - fn truncate(self: &mut BridgeStream<'_>, length: i64); - fn tell(self: &mut BridgeStream<'_>) -> i64; - fn length(self: &mut BridgeStream<'_>) -> i64; - fn is_readonly(self: &BridgeStream<'_>) -> bool; + fn name(self: &mut TIOStream<'_>) -> String; + fn read(self: &mut TIOStream<'_>, buffer: &mut [u8]) -> usize; + fn write(self: &mut TIOStream<'_>, data: &[u8]); + fn seek(self: &mut TIOStream<'_>, offset: i64, whence: i32); + fn truncate(self: &mut TIOStream<'_>, length: i64); + fn tell(self: &mut TIOStream<'_>) -> i64; + fn length(self: &mut TIOStream<'_>) -> i64; + fn is_readonly(self: &TIOStream<'_>) -> bool; } #[namespace = "taglib_shim"] @@ -40,7 +38,7 @@ mod bridge_impl { fn thisFile(self: Pin<&TFileRef>) -> *mut BaseFile; // Create a RustIOStream from a BridgeStream - unsafe fn new_RustIOStream(stream: Pin<&mut BridgeStream>) -> UniquePtr; + unsafe fn new_RustIOStream(stream: Pin<&mut TIOStream>) -> UniquePtr; // Create a FileRef from an iostream fn new_FileRef_from_stream(stream: UniquePtr) -> UniquePtr; @@ -154,3 +152,60 @@ mod bridge_impl { } pub use bridge_impl::*; + +use std::io::SeekFrom; +use std::pin::Pin; +use super::file::IOStream; + +#[repr(C)] +pub(super) struct TIOStream<'a>(Box); + +impl<'a> TIOStream<'a> { + pub fn new(stream: T) -> Pin> { + Box::pin(TIOStream(Box::new(stream))) + } + + + // Implement the exposed functions for cxx bridge + pub fn name(&mut self) -> String { + self.0.name() + } + + pub fn read(&mut self, buffer: &mut [u8]) -> usize { + self.0.read(buffer).unwrap_or(0) + } + + pub fn write(&mut self, data: &[u8]) { + self.0.write_all(data).unwrap(); + } + + pub fn seek(&mut self, offset: i64, whence: i32) { + let pos = match whence { + 0 => SeekFrom::Start(offset as u64), + 1 => SeekFrom::Current(offset), + 2 => SeekFrom::End(offset), + _ => panic!("Invalid seek whence"), + }; + self.0.seek(pos).unwrap(); + } + + pub fn truncate(&mut self, length: i64) { + self.0.seek(SeekFrom::Start(length as u64)).unwrap(); + // TODO: Actually implement truncate once we have a better trait bound + } + + pub fn tell(&mut self) -> i64 { + self.0.seek(SeekFrom::Current(0)).unwrap() as i64 + } + + pub fn length(&mut self) -> i64 { + let current = self.0.seek(SeekFrom::Current(0)).unwrap(); + let end = self.0.seek(SeekFrom::End(0)).unwrap(); + self.0.seek(SeekFrom::Start(current)).unwrap(); + end as i64 + } + + pub fn is_readonly(&self) -> bool { + self.0.is_readonly() + } +} diff --git a/musikr/src/main/jni/src/taglib/file.rs b/musikr/src/main/jni/src/taglib/file.rs index 296842eb3..2c67b4068 100644 --- a/musikr/src/main/jni/src/taglib/file.rs +++ b/musikr/src/main/jni/src/taglib/file.rs @@ -1,21 +1,19 @@ use cxx::UniquePtr; -use super::bridge::{self, TFileRef}; +use super::bridge::{self, TFileRef, TIOStream}; pub use super::bridge::{BaseFile as File, AudioProperties}; use super::xiph::{OpusFile, VorbisFile, FLACFile}; -use super::stream::BridgeStream; -use super::stream::IOStream; +use std::io::{Read, Write, Seek}; use std::pin::Pin; -use std::marker::PhantomData; pub struct FileRef<'a> { - stream: BridgeStream<'a>, + stream: Pin>>, file_ref: UniquePtr } impl <'a> FileRef<'a> { pub fn new(stream: T) -> FileRef<'a> { - let mut bridge_stream = BridgeStream::new(stream); - let iostream = unsafe { bridge::new_RustIOStream(Pin::new(&mut bridge_stream)) }; + let mut bridge_stream = TIOStream::new(stream); + let iostream = unsafe { bridge::new_RustIOStream(bridge_stream.as_mut()) }; let file_ref = bridge::new_FileRef_from_stream(iostream); FileRef { stream: bridge_stream, @@ -196,4 +194,9 @@ impl <'a> Drop for FileRef<'a> { std::ptr::drop_in_place(&mut self.stream); } } -} \ No newline at end of file +} + +pub trait IOStream: Read + Write + Seek { + fn name(&mut self) -> String; + fn is_readonly(&self) -> bool; +} diff --git a/musikr/src/main/jni/src/taglib/mod.rs b/musikr/src/main/jni/src/taglib/mod.rs index 201e282b5..e429734ea 100644 --- a/musikr/src/main/jni/src/taglib/mod.rs +++ b/musikr/src/main/jni/src/taglib/mod.rs @@ -1,6 +1,5 @@ mod bridge; pub mod file; -pub mod stream; pub mod tk; pub mod xiph; diff --git a/musikr/src/main/jni/src/taglib/stream.rs b/musikr/src/main/jni/src/taglib/stream.rs deleted file mode 100644 index fa0096da5..000000000 --- a/musikr/src/main/jni/src/taglib/stream.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::ffi::{c_void, CString}; -use std::io::{Read, Seek, SeekFrom, Write}; -use std::os::raw::c_char; -use cxx::CxxString; - -pub trait IOStream: Read + Write + Seek { - fn name(&mut self) -> String; - fn is_readonly(&self) -> bool; -} - -#[repr(C)] -pub(super) struct BridgeStream<'a>(Box); - -impl<'a> BridgeStream<'a> { - pub fn new(stream: T) -> Self { - BridgeStream(Box::new(stream)) - } - - // Implement the exposed functions for cxx bridge - pub fn name(&mut self) -> String { - self.0.name() - } - - pub fn read(&mut self, buffer: &mut [u8]) -> usize { - self.0.read(buffer).unwrap_or(0) - } - - pub fn write(&mut self, data: &[u8]) { - self.0.write_all(data).unwrap(); - } - - pub fn seek(&mut self, offset: i64, whence: i32) { - let pos = match whence { - 0 => SeekFrom::Start(offset as u64), - 1 => SeekFrom::Current(offset), - 2 => SeekFrom::End(offset), - _ => panic!("Invalid seek whence"), - }; - self.0.seek(pos).unwrap(); - } - - pub fn truncate(&mut self, length: i64) { - self.0.seek(SeekFrom::Start(length as u64)).unwrap(); - // TODO: Actually implement truncate once we have a better trait bound - } - - pub fn tell(&mut self) -> i64 { - self.0.seek(SeekFrom::Current(0)).unwrap() as i64 - } - - pub fn length(&mut self) -> i64 { - let current = self.0.seek(SeekFrom::Current(0)).unwrap(); - let end = self.0.seek(SeekFrom::End(0)).unwrap(); - self.0.seek(SeekFrom::Start(current)).unwrap(); - end as i64 - } - - pub fn is_readonly(&self) -> bool { - self.0.is_readonly() - } -}