wincorda
win (Windows) + corda (string)
A Rust library for Windows strings.
Examples
Null terminated string from const pointer:
use wincorda::prelude::*;
let data = b"hello, world!\0";
let nt = NullTerminated::<UCHAR>::try_from(data).unwrap();
// or NullTerminated::<CHAR>::try_from(data) — same bytes, i8 element type
assert_eq!(nt, "hello, world!");This will borrow the data at the time of the
try_from, and they may later become owned depending on API usage.
Null terminated string from mutable pointer:
use wincorda::prelude::*;
use winapi::um::processenv::GetCommandLineW;
let nt = NullTerminated::try_from(unsafe { GetCommandLineW() }); // NullTerminated<WCHAR>This will copy the underlying contents at the time of the
try_fromto avoid working with inconsistent data.
Passing null terminated string buffer to APIs that take mutable pointers:
use std::num::NonZeroUsize;
use std::ptr::null_mut;
use wincorda::prelude::*;
use winapi::{um::libloaderapi::GetModuleFileNameA, shared::minwindef::MAX_PATH};
let size = NonZeroUsize::new(MAX_PATH * 2).unwrap();
let mut buf = NullTerminated::zeroed(size); // NullTerminated<CHAR>, inferred from line below
let res = unsafe { GetModuleFileNameA(null_mut(), buf.as_mut_ptr(), size.get() as _) };
// RECOMMENDED: shrink buffer capacity at null
buf.shrink_to_null();WARNING: calling
NullTerminated::as_mut_ptrguarantees that the underlying contents will become owned.If you're asked for a mutable pointer by an API, but you know for sure that the contents will not be changed in the operation, you may choose to instead use
NullTerminated::as_ptrand then a cast to*const T.
Multi string (REG_MULTI_SZ/environment/ImGui UI/etc, double-null-terminated style) buffer from const pointer:
use wincorda::prelude::*;
use winapi::um::processenv::GetEnvironmentStringsW;
let mb = MultiBuffer::try_from(unsafe { GetEnvironmentStringsW() }).unwrap(); // MultiBuffer<WCHAR>
for entry in mb.iter() {
// `entry` is `NullTerminated`.
println!("{entry}");
}Building a multi-string buffer from a list of strings and passing it to ImGui:
use wincorda::prelude::*;
// From &[&str], Vec<&str>, Vec<String>, &[String] — all work
let items: MultiBuffer<CHAR> = vec!["Alpha", "Beta", "Gamma"].into();
let mut current = 0i32;
unsafe {
// igCombo expects *const CHAR → "Alpha\0Beta\0Gamma\0\0"
igCombo(
b"##combo\0".as_ptr() as _,
&mut current,
items.as_ptr(),
items.count() as _,
);
}Building a multi-string buffer at runtime from dynamic data:
use wincorda::prelude::*;
let choices: Vec<String> = load_options_from_config(); // your data source
let items: MultiBuffer<CHAR> = choices.into();
// items.as_ptr() → *const CHAR, ready for any C API
// items.strings() → Iterator<Item = String>, for Rust-side consumption
for label in items.strings() {
println!("{label}");
}Support
- Null-terminated strings
- Double-null-terminated multi-buffer of null-terminated strings (e.g. environment)