From a959f7a2ad3e983dd1753d39244c8135108b8013 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 26 Jan 2022 21:02:52 +0100 Subject: [PATCH] Add an UTF-16 equivalent for strlcpy() --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/wrapper/util.rs | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 689be2b7..256b1267 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,7 @@ version = "0.1.0" dependencies = [ "nih_plug_derive", "vst3-sys", + "widestring", ] [[package]] @@ -96,3 +97,9 @@ source = "git+https://github.com/robbert-vdh/vst3-sys.git?branch=fix/vst3-macro- dependencies = [ "vst3-com", ] + +[[package]] +name = "widestring" +version = "1.0.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f1efe828a707edf85994a4501734ac1c1b9d244cfcf4de235f11c4125ace8f" diff --git a/Cargo.toml b/Cargo.toml index 534d3e14..a2460ecb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ members = ["nih_plug_derive", "plugins/gain"] nih_plug_derive = { path = "nih_plug_derive" } # Upstream currently does not support structs with generics and comments vst3-sys = { git = "https://github.com/robbert-vdh/vst3-sys.git", branch = "fix/vst3-macro-generics" } +widestring = "1.0.0-beta.1" diff --git a/src/wrapper/util.rs b/src/wrapper/util.rs index 5f33eeed..d3e084a0 100644 --- a/src/wrapper/util.rs +++ b/src/wrapper/util.rs @@ -16,6 +16,8 @@ use std::cmp; use std::os::raw::c_char; +use vst3_sys::vst::TChar; +use widestring::U16CString; /// The equivalent of the `strlcpy()` C function. Copy `src` to `dest` as a null-terminated /// C-string. If `dest` does not have enough capacity, add a null terminator at the end to prevent @@ -33,3 +35,26 @@ pub fn strlcpy(dest: &mut [c_char], src: &str) { dest[..copy_len].copy_from_slice(&src_bytes_signed[..copy_len]); dest[copy_len] = 0; } + +/// The same as [strlcpy], but for VST3's fun UTF-16 strings instead. +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) => { + nih_debug_assert_failure!("Invalid UTF-16 string: {}", err); + return; + } + }; + let src_utf16_chars = src_utf16.as_slice(); + let src_utf16_chars_signed: &[TChar] = + unsafe { &*(src_utf16_chars as *const [u16] as *const [TChar]) }; + + // Make sure there's always room for a null terminator + let copy_len = cmp::min(dest.len() - 1, src_utf16_chars_signed.len()); + dest[..copy_len].copy_from_slice(&src_utf16_chars_signed[..copy_len]); + dest[copy_len] = 0; +}