v0.12.0: Rust 2024 edition migration
- edition = "2024" bump.
- FFI block in src/scsi/macos.rs wrapped in `unsafe extern "C" { }`.
- vtable_fn body gets an explicit unsafe block (unsafe_op_in_unsafe_fn).
- Match-ergonomics cleanup in mux/meta.rs, mkvstream.rs, network.rs,
stdio.rs — removed redundant `ref` / `ref mut` bindings.
MSRV unchanged at 1.86. 226 tests pass. No behavior change.
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.12.0 (2026-04-24)
|
||||||
|
|
||||||
|
### Rust 2024 edition migration
|
||||||
|
- Bumped `edition = "2024"`. Required code changes:
|
||||||
|
- FFI declarations in `src/scsi/macos.rs` wrapped in `unsafe extern "C" { … }` per the 2024 FFI safety rules.
|
||||||
|
- `unsafe_op_in_unsafe_fn` lint: `vtable_fn()` body now has an explicit `unsafe { … }` block rather than relying on implicit unsafe of the containing `unsafe fn`.
|
||||||
|
- Match-ergonomics: removed redundant `ref`/`ref mut` bindings in `mux/meta.rs`, `mux/mkvstream.rs`, `mux/network.rs`, `mux/stdio.rs` — 2024 tightens "cannot explicitly borrow within an implicitly-borrowing pattern."
|
||||||
|
- No behavior change. MSRV stays at 1.86.
|
||||||
|
|
||||||
|
### Minor / version sync
|
||||||
|
- Part of the 0.12.0 ecosystem release. The autorip-side fixes (progress regressions, UI redesign, regression-guard tests) drove the minor bump.
|
||||||
|
|
||||||
## 0.11.22 (2026-04-24)
|
## 0.11.22 (2026-04-24)
|
||||||
|
|
||||||
### Version sync — no functional changes
|
### Version sync — no functional changes
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfreemkv"
|
name = "libfreemkv"
|
||||||
version = "0.11.22"
|
version = "0.12.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
rust-version = "1.86"
|
rust-version = "1.86"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
description = "Open source raw disc access library for optical drives"
|
description = "Open source raw disc access library for optical drives"
|
||||||
|
|||||||
+1
-1
@@ -211,7 +211,7 @@ impl M2tsMeta {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
if let MetaStream::Video {
|
if let MetaStream::Video {
|
||||||
codec_private: Some(ref b64),
|
codec_private: Some(b64),
|
||||||
..
|
..
|
||||||
} = s
|
} = s
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ impl crate::pes::Stream for MkvStream {
|
|||||||
|
|
||||||
fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
|
fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
|
||||||
match &mut self.mode {
|
match &mut self.mode {
|
||||||
Mode::Write {
|
Mode::Write { muxer: Some(m) } => {
|
||||||
muxer: Some(ref mut m),
|
m.write_frame(frame.track, frame.pts, frame.keyframe, &frame.data)
|
||||||
} => m.write_frame(frame.track, frame.pts, frame.keyframe, &frame.data),
|
}
|
||||||
Mode::Write { muxer: None } => Ok(()),
|
Mode::Write { muxer: None } => Ok(()),
|
||||||
Mode::Read(_) => Err(crate::error::Error::StreamReadOnly.into()),
|
Mode::Read(_) => Err(crate::error::Error::StreamReadOnly.into()),
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ impl crate::pes::Stream for NetworkStream {
|
|||||||
match &mut self.mode {
|
match &mut self.mode {
|
||||||
Mode::Write {
|
Mode::Write {
|
||||||
writer,
|
writer,
|
||||||
ref mut header_written,
|
header_written,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if !*header_written {
|
if !*header_written {
|
||||||
|
|||||||
+1
-1
@@ -70,7 +70,7 @@ impl crate::pes::Stream for StdioStream {
|
|||||||
}
|
}
|
||||||
fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
|
fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
|
||||||
match &mut self.writer {
|
match &mut self.writer {
|
||||||
Some(ref mut w) => {
|
Some(w) => {
|
||||||
if !self.header_written {
|
if !self.header_written {
|
||||||
if !self.disc_title.streams.is_empty() {
|
if !self.disc_title.streams.is_empty() {
|
||||||
let m = meta::M2tsMeta::from_title(&self.disc_title);
|
let m = meta::M2tsMeta::from_title(&self.disc_title);
|
||||||
|
|||||||
+10
-1
@@ -63,7 +63,8 @@ struct SCSITaskSGElement {
|
|||||||
|
|
||||||
// ── External IOKit / CoreFoundation functions ───────────────────────────────
|
// ── External IOKit / CoreFoundation functions ───────────────────────────────
|
||||||
|
|
||||||
extern "C" {
|
// Rust 2024: FFI blocks declaring extern fns must be `unsafe extern`.
|
||||||
|
unsafe extern "C" {
|
||||||
fn IOMasterPort(bootstrap: u32, master: *mut MachPort) -> IOReturn;
|
fn IOMasterPort(bootstrap: u32, master: *mut MachPort) -> IOReturn;
|
||||||
fn IOBSDNameMatching(
|
fn IOBSDNameMatching(
|
||||||
master: MachPort,
|
master: MachPort,
|
||||||
@@ -97,10 +98,18 @@ extern "C" {
|
|||||||
// IOSCSIArchitectureModelFamily/UserClientLib/SCSITaskLib.h
|
// IOSCSIArchitectureModelFamily/UserClientLib/SCSITaskLib.h
|
||||||
|
|
||||||
/// Read a function pointer from a COM vtable at the given index.
|
/// Read a function pointer from a COM vtable at the given index.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `iface` must be a valid COM interface pointer (*mut *mut c_void), and
|
||||||
|
/// `index` must be a valid vtable slot for the target type `T`.
|
||||||
unsafe fn vtable_fn<T>(iface: ComRef, index: usize) -> T {
|
unsafe fn vtable_fn<T>(iface: ComRef, index: usize) -> T {
|
||||||
|
// Rust 2024: `unsafe fn` bodies are no longer implicitly unsafe.
|
||||||
|
// Each unsafe op needs its own `unsafe { }` block.
|
||||||
|
unsafe {
|
||||||
let vtable = *iface as *const *const std::ffi::c_void;
|
let vtable = *iface as *const *const std::ffi::c_void;
|
||||||
let fn_ptr = *vtable.add(index);
|
let fn_ptr = *vtable.add(index);
|
||||||
std::mem::transmute_copy(&fn_ptr)
|
std::mem::transmute_copy(&fn_ptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call Release (vtable index 3) on any COM interface.
|
/// Call Release (vtable index 3) on any COM interface.
|
||||||
|
|||||||
Reference in New Issue
Block a user