use std::{cmp, ffi::CStr};
use vst3::Steinberg::{FIDString, Vst::TChar};
use widestring::U16CString;
pub const VST3_MIDI_CCS: u32 = 130;
pub const VST3_MIDI_CHANNELS: u32 = 16;
pub const VST3_MIDI_NUM_PARAMS: u32 = VST3_MIDI_CCS * VST3_MIDI_CHANNELS;
pub const VST3_MIDI_PARAMS_START: u32 = VST3_MIDI_PARAMS_END - VST3_MIDI_NUM_PARAMS;
pub const VST3_MIDI_PARAMS_END: u32 = 1 << 31;
macro_rules! check_null_ptr {
($ptr:expr $(, $ptrs:expr)* $(, )?) => {
check_null_ptr_msg!("Null pointer passed to function", $ptr $(, $ptrs)*)
};
}
macro_rules! check_null_ptr_msg {
($msg:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
if $ptr.is_null() $(|| $ptrs.is_null())* {
crate::nice_debug_assert_failure!($msg);
return kInvalidArgument;
}
};
}
pub fn u16strlcpy(dest: &mut [TChar], src: &str) {
if dest.is_empty() {
return;
}
let src_utf16 = match U16CString::from_str(src) {
Ok(s) => s,
Err(err) => {
crate::nice_debug_assert_failure!("Invalid UTF-16 string: {}", err);
return;
}
};
let src_utf16_chars = src_utf16.as_slice();
let copy_len = cmp::min(dest.len() - 1, src_utf16_chars.len());
dest[..copy_len].copy_from_slice(&src_utf16_chars[..copy_len]);
dest[copy_len] = 0;
}
pub unsafe fn fid_matches(type_: FIDString, expected: FIDString) -> bool {
unsafe { !type_.is_null() && CStr::from_ptr(type_) == CStr::from_ptr(expected) }
}
#[cfg(test)]
mod miri {
use widestring::U16CStr;
use super::*;
#[test]
fn u16strlcpy_normal() {
let mut dest = [0; 256];
u16strlcpy(&mut dest, "Hello, world!");
assert_eq!(
unsafe { U16CStr::from_ptr_str(dest.as_ptr() as *const u16) }
.to_string()
.unwrap(),
"Hello, world!"
);
}
#[test]
fn u16strlcpy_overflow() {
let mut dest = [0; 6];
u16strlcpy(&mut dest, "Hello, world!");
assert_eq!(
unsafe { U16CStr::from_ptr_str(dest.as_ptr() as *const u16) }
.to_string()
.unwrap(),
"Hello"
);
}
}