use std::ffi::{CStr, CString};
use std::os::raw::c_char;
pub fn strip_dual_endings(s: &str) -> String {
s.replace("\r\n", "\n")
}
pub fn insert_dual_endings(s: &str) -> String {
let mut ns = String::with_capacity(s.len());
let mut cr = false;
for (_, d) in s.char_indices() {
if d == '\n' && !cr {
ns.push('\r');
}
ns.push(d);
cr = d == '\r';
}
return ns;
}
pub fn to_toolkit_string(s: &str) -> CString {
let data = if cfg!(windows) {
insert_dual_endings(s).as_bytes().to_vec()
} else {
s.as_bytes().to_vec()
};
CString::new(data).expect(&format!("Failed to create CString from {}", s))
}
pub unsafe fn from_toolkit_string(c: *mut c_char) -> String {
CStr::from_ptr(c).to_string_lossy().into_owned()
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn strip_dual_endings_to_single() {
assert_eq!(
strip_dual_endings("Line 1\r\nLine 2\r\n"),
"Line 1\nLine 2\n"
);
}
#[test]
fn insert_dual_endings_basic() {
assert_eq!(
insert_dual_endings("Line 1\nLine 2\n"),
"Line 1\r\nLine 2\r\n"
);
}
#[test]
fn insert_dual_endings_nodupe() {
assert_eq!(
insert_dual_endings("Line 1\r\nLine 2\r\n"),
"Line 1\r\nLine 2\r\n"
);
}
#[test]
fn test_toolkit_roundtripping() {
let initial_string = "Here is some test data.\n\nMultiline!\n";
let toolkit_string = to_toolkit_string(initial_string);
let roundtripped_string = unsafe { from_toolkit_string(toolkit_string.into_raw()) };
assert_eq!(initial_string, &roundtripped_string);
}
}