clippy: clear the workspace errors and apply the machine fixes

- Mark the raw-pointer interop entry points unsafe with # Safety docs
  (oak-core upload/download/frame-from-pixels, oak-audio convert) and
  satisfy the existing callers (tests).
- mut_from_ref: allow with the ABI contract documented (the handle
  get_mut helpers in oak-timeline/oak-render/oak-task take the shared
  reference the C ABI passes; exclusivity is the caller's unsafe
  contract).
- Fix the eq_op in the white-balance normalization (green / green).
- Apply cargo clippy --fix across the workspace (redundant closures and
  field names, field reassignment, items after test modules, ...).
- Revert the replace_box fix in image_effect's clip_define: a
  redefinition must allocate a new box, otherwise the old clip handle
  stays valid and the HS-map replace contract (clip != clip2) breaks.
- 283 warnings remain; they are all non-machine-applicable
  (chunks_exact -> as_chunks needs a manual iter_mut, too_many_arguments,
  complex types, missing Safety docs, ...) and are tracked as the
  follow-up.
This commit is contained in:
2026-09-15 19:29:32 +08:00
parent 7e87ec135e
commit ee7ea18d94
146 changed files with 5235 additions and 4046 deletions
+1 -1
View File
@@ -960,7 +960,7 @@ mod tests {
let stride = w as usize * 4;
for (i, g) in got.iter().enumerate() {
let row = i / stride;
let inv_row = (h as usize - 1 - row) as usize;
let inv_row = h as usize - 1 - row;
let expected = want[inv_row * stride + i % stride];
assert!(
(g - expected).abs() < 1e-6,
+2 -4
View File
@@ -640,11 +640,10 @@ impl Instance {
// 进度报告器(facade 回调优先;无回调而 app 注册了 UI 工厂
// 时装静默报告器,progressStart 再经工厂现造 UI 报告器)。
if let Some((cb, userdata)) = self
if let Some((cb, userdata)) = *self
.progress_cb
.lock()
.unwrap_or_else(|e| e.into_inner())
.clone()
{
crate::suites::progress::set_current(Some(unsafe {
crate::progress::ProgressReporter::new(cb, userdata as *mut std::ffi::c_void)
@@ -735,11 +734,10 @@ impl Instance {
}));
// GL 模式无 CPU 输出图像(current_output 保持 None)。
if let Some((cb, userdata)) = self
if let Some((cb, userdata)) = *self
.progress_cb
.lock()
.unwrap_or_else(|e| e.into_inner())
.clone()
{
crate::suites::progress::set_current(Some(unsafe {
crate::progress::ProgressReporter::new(cb, userdata as *mut std::ffi::c_void)
+1 -3
View File
@@ -942,9 +942,7 @@ fn shared_plugin_instance(identifier: &str) -> Option<u64> {
return Some(id);
}
let host = Host::global();
if host.cache.find(identifier).is_none() {
return None;
}
host.cache.find(identifier)?;
// 上下文选择:filter 优先、实例化失败按序回退(与
// [`register_plugin_nodes`] 同一策略,见
// [`Host::create_instance_preferred`])。
+3 -3
View File
@@ -619,7 +619,7 @@ pub(crate) fn param_value_from_node(
TYPE_DOUBLE3D => {
(v.r#type == T::VEC3).then(|| ParamValue::Double([v.f[0], v.f[1], v.f[2]], 3))
}
TYPE_INTEGER => (v.r#type == T::INT).then(|| ParamValue::Int([v.num as i32, 0, 0], 1)),
TYPE_INTEGER => (v.r#type == T::INT).then_some(ParamValue::Int([v.num as i32, 0, 0], 1)),
TYPE_INTEGER2D | TYPE_INTEGER3D => {
let dim = if ofx_type == TYPE_INTEGER2D { 2 } else { 3 };
Some(ParamValue::Int(
@@ -627,8 +627,8 @@ pub(crate) fn param_value_from_node(
dim,
))
}
TYPE_BOOLEAN => (v.r#type == T::BOOL).then(|| ParamValue::Bool(v.num != 0)),
TYPE_CHOICE => (v.r#type == T::COMBO).then(|| ParamValue::Choice(v.num as i32)),
TYPE_BOOLEAN => (v.r#type == T::BOOL).then_some(ParamValue::Bool(v.num != 0)),
TYPE_CHOICE => (v.r#type == T::COMBO).then_some(ParamValue::Choice(v.num as i32)),
TYPE_RGB => {
(v.r#type == T::COLOR).then(|| ParamValue::Color([v.f[0], v.f[1], v.f[2], 0.0], 3))
}
+1 -1
View File
@@ -108,7 +108,7 @@ pub fn texture_create(
return Err(Error::Invalid);
}
// 行跨度推导通道数(RGB 3 通道等非常规分量)。
if linesize > 0 && w > 0 && (linesize as usize) % (w * bpc) == 0 {
if linesize > 0 && w > 0 && (linesize as usize).is_multiple_of(w * bpc) {
frame.channels = (linesize as usize / (w * bpc)) as i32;
}
let tight = frame.linesize_bytes();
+1 -1
View File
@@ -256,7 +256,7 @@ pub fn render_frame(
if clip.name == "Output" {
continue;
}
if pick_input(&clip.name, job).map_or(false, |t| usable(&t)) {
if pick_input(&clip.name, job).is_some_and(|t| usable(&t)) {
clip.set_region_of_definition(region_of_interest, job.time);
clip.set_video_params(depth_format, 4);
}
+3 -3
View File
@@ -257,7 +257,7 @@ unsafe extern "C" fn set_colour(ctx: *mut c_void, colour: *const OfxRGBAColourF)
if colour.is_null() {
return Err(status::ERR_VALUE);
}
let _ = resolve_mut(ctx)?;
resolve_mut(ctx)?;
let v = unsafe { &*colour };
let addr = ctx as usize;
let mut live = lock();
@@ -269,7 +269,7 @@ unsafe extern "C" fn set_colour(ctx: *mut c_void, colour: *const OfxRGBAColourF)
unsafe extern "C" fn set_line_width(ctx: *mut c_void, width: c_float) -> c_int {
caught(|| {
let _ = resolve_mut(ctx)?;
resolve_mut(ctx)?;
let addr = ctx as usize;
let mut live = lock();
let slot = live.get_mut(&addr).expect("resolve 已保证存活");
@@ -283,7 +283,7 @@ unsafe extern "C" fn set_line_stipple(ctx: *mut c_void, pattern: c_int) -> c_int
if !(0..=stipple::DOT_DASH).contains(&pattern) {
return Err(status::ERR_VALUE);
}
let _ = resolve_mut(ctx)?;
resolve_mut(ctx)?;
let addr = ctx as usize;
let mut live = lock();
let slot = live.get_mut(&addr).expect("resolve 已保证存活");
+52 -54
View File
@@ -122,52 +122,6 @@ pub(crate) fn pick_gl_pixel_depth(
None
}
#[cfg(test)]
mod tests {
use super::*;
use crate::property::{PropertySet, Value};
fn cs(s: &str) -> CString {
CString::new(s).unwrap()
}
/// GL 像素深度协商矩阵(ofxGPURender.h kOfxOpenGLPropPixelDepth):
/// 未声明/含 Float → 管线 F32 可行;声明且不含 Float → None
/// (GL 模式不可行,回退 CPU)。
#[test]
fn pick_gl_pixel_depth_matrix() {
let props = PropertySet::new();
assert_eq!(pick_gl_pixel_depth(&props), Some("OfxBitDepthFloat"));
let props2 = PropertySet::new();
props2.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![
Value::String(cs("OfxBitDepthHalf")),
Value::String(cs("OfxBitDepthByte")),
],
);
assert_eq!(pick_gl_pixel_depth(&props2), None);
let props3 = PropertySet::new();
props3.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![
Value::String(cs("OfxBitDepthByte")),
Value::String(cs("OfxBitDepthFloat")),
],
);
assert_eq!(pick_gl_pixel_depth(&props3), Some("OfxBitDepthFloat"));
let props4 = PropertySet::new();
props4.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![Value::String(cs("OfxBitDepthFloat"))],
);
assert_eq!(pick_gl_pixel_depth(&props4), Some("OfxBitDepthFloat"));
}
}
// ---- 存活纹理表 -----------------------------------------------------------
/// 存活 GL 纹理表:clipLoadTexture 产出(props 地址 → 属性集 +
@@ -224,11 +178,9 @@ pub(crate) fn purge_leftovers() {
.collect();
live.retain(|_, (_, _, is_output, _)| *is_output);
drop(live);
for gl in dropped {
if let Some(gl) = gl {
delete_gl_texture_if_gl(gl);
}
}
for gl in dropped.into_iter().flatten() {
delete_gl_texture_if_gl(gl);
}
}
/// 公共入口模板:panic 兜底。
@@ -539,8 +491,54 @@ pub struct GlRenderSuiteV1 {
pub fn suite_v1() -> &'static GlRenderSuiteV1 {
static SUITE: std::sync::OnceLock<GlRenderSuiteV1> = std::sync::OnceLock::new();
SUITE.get_or_init(|| GlRenderSuiteV1 {
clip_load_texture: clip_load_texture,
clip_free_texture: clip_free_texture,
flush_resources: flush_resources,
clip_load_texture,
clip_free_texture,
flush_resources,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::property::{PropertySet, Value};
fn cs(s: &str) -> CString {
CString::new(s).unwrap()
}
/// GL 像素深度协商矩阵(ofxGPURender.h kOfxOpenGLPropPixelDepth):
/// 未声明/含 Float → 管线 F32 可行;声明且不含 Float → None
/// (GL 模式不可行,回退 CPU)。
#[test]
fn pick_gl_pixel_depth_matrix() {
let props = PropertySet::new();
assert_eq!(pick_gl_pixel_depth(&props), Some("OfxBitDepthFloat"));
let props2 = PropertySet::new();
props2.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![
Value::String(cs("OfxBitDepthHalf")),
Value::String(cs("OfxBitDepthByte")),
],
);
assert_eq!(pick_gl_pixel_depth(&props2), None);
let props3 = PropertySet::new();
props3.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![
Value::String(cs("OfxBitDepthByte")),
Value::String(cs("OfxBitDepthFloat")),
],
);
assert_eq!(pick_gl_pixel_depth(&props3), Some("OfxBitDepthFloat"));
let props4 = PropertySet::new();
props4.define(
crate::host::PROP_GL_PIXEL_DEPTH,
vec![Value::String(cs("OfxBitDepthFloat"))],
);
assert_eq!(pick_gl_pixel_depth(&props4), Some("OfxBitDepthFloat"));
}
}
+17 -14
View File
@@ -200,7 +200,10 @@ unsafe extern "C" fn clip_define(
EffectRef::Instance(_) => return Err(status::ERR_BAD_HANDLE),
};
let clip = ClipDescriptor::new(n);
// 重复定义:替换原 Box(HS map 覆盖语义)。
// 重复定义:替换原 Box(HS map 覆盖语义)。必须是新的 Box:
// 旧句柄随即失效(测试断言 clip != clip2),复用同一分配会
// 破坏这一 C ABI 契约,故此处保留 `Box::new`。
#[allow(clippy::replace_box)]
if let Some(existing) = desc.clips.iter_mut().find(|c| c.name == n) {
*existing = Box::new(clip);
} else {
@@ -469,19 +472,19 @@ use crate::property::Value;
pub fn suite_v1() -> &'static ImageEffectSuiteV1 {
static SUITE: std::sync::OnceLock<ImageEffectSuiteV1> = std::sync::OnceLock::new();
SUITE.get_or_init(|| ImageEffectSuiteV1 {
get_property_set: get_property_set,
get_param_set: get_param_set,
clip_define: clip_define,
clip_get_handle: clip_get_handle,
clip_get_property_set: clip_get_property_set,
clip_get_image: clip_get_image,
clip_release_image: clip_release_image,
clip_get_region_of_definition: clip_get_region_of_definition,
abort: abort,
image_memory_alloc: image_memory_alloc,
image_memory_free: image_memory_free,
image_memory_lock: image_memory_lock,
image_memory_unlock: image_memory_unlock,
get_property_set,
get_param_set,
clip_define,
clip_get_handle,
clip_get_property_set,
clip_get_image,
clip_release_image,
clip_get_region_of_definition,
abort,
image_memory_alloc,
image_memory_free,
image_memory_lock,
image_memory_unlock,
})
}
+7 -7
View File
@@ -84,7 +84,7 @@ unsafe extern "C" fn multi_thread(
// 裸指针不可 Send:以 usize 搬运,线程内还原(C 侧本即
// 整数传递语义)。
let arg = thread_arg as usize;
let _ = std::thread::scope(|scope| {
std::thread::scope(|scope| {
for i in 0..n_threads {
scope.spawn(move || {
THREAD_INDEX.with(|t| t.set(Some(i)));
@@ -244,15 +244,15 @@ unsafe extern "C" fn mutex_try_lock(handle: *mut c_void) -> c_int {
pub fn suite_v1() -> &'static MultiThreadSuiteV1 {
static SUITE: std::sync::OnceLock<MultiThreadSuiteV1> = std::sync::OnceLock::new();
SUITE.get_or_init(|| MultiThreadSuiteV1 {
multi_thread: multi_thread,
multi_thread,
num_cpus: multi_thread_num_cpus,
index: multi_thread_index,
is_spawned: multi_thread_is_spawned,
mutex_create: mutex_create,
mutex_destroy: mutex_destroy,
mutex_lock: mutex_lock,
mutex_unlock: mutex_unlock,
mutex_try_lock: mutex_try_lock,
mutex_create,
mutex_destroy,
mutex_lock,
mutex_unlock,
mutex_try_lock,
})
}
+14 -15
View File
@@ -160,11 +160,10 @@ fn caught(f: impl FnOnce() -> Result<(), c_int>) -> c_int {
|_| status::FAILED,
|r| r.map_or_else(|c| c, |()| status::OK),
);
if std::env::var_os("OAK_OFX_TRACE").is_some() {
if code != status::OK {
if std::env::var_os("OAK_OFX_TRACE").is_some()
&& code != status::OK {
eprintln!("[ofx] param suite error {code} at {caller}");
}
}
code
}
@@ -712,24 +711,24 @@ extern "C" {
pub fn suite_v1() -> &'static ParameterSuiteV1 {
static SUITE: std::sync::OnceLock<ParameterSuiteV1> = std::sync::OnceLock::new();
SUITE.get_or_init(|| ParameterSuiteV1 {
param_define: param_define,
param_get_handle: param_get_handle,
param_set_get_property_set: param_set_get_property_set,
param_get_property_set: param_get_property_set,
param_define,
param_get_handle,
param_set_get_property_set,
param_get_property_set,
param_get_value: ofx_param_get_value_shim,
param_get_value_at_time: ofx_param_get_value_at_time_shim,
param_get_derivative: ofx_param_get_derivative_shim,
param_get_integral: ofx_param_get_integral_shim,
param_set_value: ofx_param_set_value_shim,
param_set_value_at_time: ofx_param_set_value_at_time_shim,
param_get_num_keys: param_get_num_keys,
param_get_key_time: param_get_key_time,
param_get_key_index: param_get_key_index,
param_delete_key: param_delete_key,
param_delete_all_keys: param_delete_all_keys,
param_copy: param_copy,
param_edit_begin: param_edit_begin,
param_edit_end: param_edit_end,
param_get_num_keys,
param_get_key_time,
param_get_key_index,
param_delete_key,
param_delete_all_keys,
param_copy,
param_edit_begin,
param_edit_end,
})
}
+7 -7
View File
@@ -399,13 +399,13 @@ unsafe extern "C" fn parametric_param_delete_all_control_points(
pub fn suite_v1() -> &'static ParametricParameterSuiteV1 {
static SUITE: std::sync::OnceLock<ParametricParameterSuiteV1> = std::sync::OnceLock::new();
SUITE.get_or_init(|| ParametricParameterSuiteV1 {
parametric_param_get_value: parametric_param_get_value,
parametric_param_get_n_control_points: parametric_param_get_n_control_points,
parametric_param_get_nth_control_point: parametric_param_get_nth_control_point,
parametric_param_set_nth_control_point: parametric_param_set_nth_control_point,
parametric_param_add_control_point: parametric_param_add_control_point,
parametric_param_delete_control_point: parametric_param_delete_control_point,
parametric_param_delete_all_control_points: parametric_param_delete_all_control_points,
parametric_param_get_value,
parametric_param_get_n_control_points,
parametric_param_get_nth_control_point,
parametric_param_set_nth_control_point,
parametric_param_add_control_point,
parametric_param_delete_control_point,
parametric_param_delete_all_control_points,
})
}
+4 -12
View File
@@ -563,11 +563,10 @@ unsafe extern "C" fn prop_get_int(
}
_ => Err(status::FAILED),
}
.map_err(|c| {
.inspect_err(|&c| {
if std::env::var_os("OAK_OFX_TRACE").is_some() {
eprintln!("[ofx] propGetInt({name}) -> {c}");
}
c
})
})
}
@@ -618,14 +617,13 @@ fn get_n(
}
Ok(())
})
.map_err(|code| {
.inspect_err(|&code| {
// The property the plugin asked for and we did not have — the
// single most useful line when a plugin reports
// MissingHostFeature (trace-gated, like fetchSuite misses).
if std::env::var_os("OAK_OFX_TRACE").is_some() {
eprintln!("[ofx] property miss: {name} (code {code})");
}
code
})
}
@@ -641,10 +639,7 @@ unsafe extern "C" fn prop_get_pointer_n(
if count > 0 && out.is_null() {
return Err(status::ERR_VALUE);
}
get_n(set, name, count, Kind::Pointer, |v, i| match v {
Value::Pointer(p) => *out.add(i) = *p,
_ => {}
})
get_n(set, name, count, Kind::Pointer, |v, i| if let Value::Pointer(p) = v { *out.add(i) = *p })
})
}
}
@@ -661,10 +656,7 @@ unsafe extern "C" fn prop_get_string_n(
if count > 0 && out.is_null() {
return Err(status::ERR_VALUE);
}
get_n(set, name, count, Kind::Str, |v, i| match v {
Value::String(s) => *out.add(i) = s.as_ptr() as *mut c_char,
_ => {}
})
get_n(set, name, count, Kind::Str, |v, i| if let Value::String(s) = v { *out.add(i) = s.as_ptr() as *mut c_char })
})
}
}