musikr: fix iostream pinning
This commit is contained in:
parent
74edd1dbdf
commit
249915c3be
5 changed files with 79 additions and 83 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::taglib::stream::IOStream;
|
use crate::taglib::file::IOStream;
|
||||||
use jni::objects::{JObject, JValue};
|
use jni::objects::{JObject, JValue};
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
use crate::SharedEnv;
|
use crate::SharedEnv;
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
use super::stream::BridgeStream;
|
|
||||||
|
|
||||||
#[cxx::bridge]
|
#[cxx::bridge]
|
||||||
mod bridge_impl {
|
mod bridge_impl {
|
||||||
// Expose Rust IOStream to C++
|
// Expose Rust IOStream to C++
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
#[cxx_name = "BridgeStream"]
|
#[cxx_name = "BridgeStream"]
|
||||||
type BridgeStream<'a>;
|
type TIOStream<'a>;
|
||||||
|
|
||||||
fn name(self: &mut BridgeStream<'_>) -> String;
|
fn name(self: &mut TIOStream<'_>) -> String;
|
||||||
fn read(self: &mut BridgeStream<'_>, buffer: &mut [u8]) -> usize;
|
fn read(self: &mut TIOStream<'_>, buffer: &mut [u8]) -> usize;
|
||||||
fn write(self: &mut BridgeStream<'_>, data: &[u8]);
|
fn write(self: &mut TIOStream<'_>, data: &[u8]);
|
||||||
fn seek(self: &mut BridgeStream<'_>, offset: i64, whence: i32);
|
fn seek(self: &mut TIOStream<'_>, offset: i64, whence: i32);
|
||||||
fn truncate(self: &mut BridgeStream<'_>, length: i64);
|
fn truncate(self: &mut TIOStream<'_>, length: i64);
|
||||||
fn tell(self: &mut BridgeStream<'_>) -> i64;
|
fn tell(self: &mut TIOStream<'_>) -> i64;
|
||||||
fn length(self: &mut BridgeStream<'_>) -> i64;
|
fn length(self: &mut TIOStream<'_>) -> i64;
|
||||||
fn is_readonly(self: &BridgeStream<'_>) -> bool;
|
fn is_readonly(self: &TIOStream<'_>) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "taglib_shim"]
|
#[namespace = "taglib_shim"]
|
||||||
|
@ -40,7 +38,7 @@ mod bridge_impl {
|
||||||
fn thisFile(self: Pin<&TFileRef>) -> *mut BaseFile;
|
fn thisFile(self: Pin<&TFileRef>) -> *mut BaseFile;
|
||||||
|
|
||||||
// Create a RustIOStream from a BridgeStream
|
// Create a RustIOStream from a BridgeStream
|
||||||
unsafe fn new_RustIOStream(stream: Pin<&mut BridgeStream>) -> UniquePtr<RustIOStream>;
|
unsafe fn new_RustIOStream(stream: Pin<&mut TIOStream>) -> UniquePtr<RustIOStream>;
|
||||||
// Create a FileRef from an iostream
|
// Create a FileRef from an iostream
|
||||||
fn new_FileRef_from_stream(stream: UniquePtr<RustIOStream>) -> UniquePtr<TFileRef>;
|
fn new_FileRef_from_stream(stream: UniquePtr<RustIOStream>) -> UniquePtr<TFileRef>;
|
||||||
|
|
||||||
|
@ -154,3 +152,60 @@ mod bridge_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use 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<dyn IOStream + 'a>);
|
||||||
|
|
||||||
|
impl<'a> TIOStream<'a> {
|
||||||
|
pub fn new<T: IOStream + 'a>(stream: T) -> Pin<Box<Self>> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
use cxx::UniquePtr;
|
use cxx::UniquePtr;
|
||||||
use super::bridge::{self, TFileRef};
|
use super::bridge::{self, TFileRef, TIOStream};
|
||||||
pub use super::bridge::{BaseFile as File, AudioProperties};
|
pub use super::bridge::{BaseFile as File, AudioProperties};
|
||||||
use super::xiph::{OpusFile, VorbisFile, FLACFile};
|
use super::xiph::{OpusFile, VorbisFile, FLACFile};
|
||||||
use super::stream::BridgeStream;
|
use std::io::{Read, Write, Seek};
|
||||||
use super::stream::IOStream;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
pub struct FileRef<'a> {
|
pub struct FileRef<'a> {
|
||||||
stream: BridgeStream<'a>,
|
stream: Pin<Box<TIOStream<'a>>>,
|
||||||
file_ref: UniquePtr<TFileRef>
|
file_ref: UniquePtr<TFileRef>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> FileRef<'a> {
|
impl <'a> FileRef<'a> {
|
||||||
pub fn new<T : IOStream + 'a>(stream: T) -> FileRef<'a> {
|
pub fn new<T : IOStream + 'a>(stream: T) -> FileRef<'a> {
|
||||||
let mut bridge_stream = BridgeStream::new(stream);
|
let mut bridge_stream = TIOStream::new(stream);
|
||||||
let iostream = unsafe { bridge::new_RustIOStream(Pin::new(&mut bridge_stream)) };
|
let iostream = unsafe { bridge::new_RustIOStream(bridge_stream.as_mut()) };
|
||||||
let file_ref = bridge::new_FileRef_from_stream(iostream);
|
let file_ref = bridge::new_FileRef_from_stream(iostream);
|
||||||
FileRef {
|
FileRef {
|
||||||
stream: bridge_stream,
|
stream: bridge_stream,
|
||||||
|
@ -196,4 +194,9 @@ impl <'a> Drop for FileRef<'a> {
|
||||||
std::ptr::drop_in_place(&mut self.stream);
|
std::ptr::drop_in_place(&mut self.stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IOStream: Read + Write + Seek {
|
||||||
|
fn name(&mut self) -> String;
|
||||||
|
fn is_readonly(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
mod bridge;
|
mod bridge;
|
||||||
|
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod stream;
|
|
||||||
pub mod tk;
|
pub mod tk;
|
||||||
pub mod xiph;
|
pub mod xiph;
|
||||||
|
|
|
@ -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<dyn IOStream + 'a>);
|
|
||||||
|
|
||||||
impl<'a> BridgeStream<'a> {
|
|
||||||
pub fn new<T: IOStream + 'a>(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()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue