GitHunt
CR

A Rust library for Windows strings.

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_from to 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_ptr guarantees 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_ptr and 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)

License

The Unlicense

Languages

Rust100.0%

Contributors

The Unlicense
Created February 3, 2026
Updated February 19, 2026
cristeigabriela/wincorda | GitHunt