stringrust

What is the best way to concatenate two rust ffi::CString?


I was unable to find a method for ffi::CString concatenation, so I did the following:

// c_str1: CString
// c_str2: CString
...
let str1 = c_str1.to_str().unwrap();
let str2 = c_str2.to_str().unwrap();
let concatenated = str1.to_owned() + str2;
...

But my solution doesn't look like an idiomatic one. Can you please suggest if there is a nicer solution for concatenation?


Solution

  • CStrings represent byte strings and not Unicode strings like str, so a more correct way to implement a generic CString concatenation would be:

    use std::ffi::{CString, CStr};
    
    fn strcat(start: CString, end: &CStr) -> CString {
        let mut concatenation = start.into_bytes();
        concatenation.extend_from_slice(end.to_bytes_with_nul());
        CString::from_vec_with_nul(concatenation).unwrap()
    }
    

    playground

    This never panics on logic errors (it’d be correct to replace the last line with unsafe { CString::from_vec_with_nul_unchecked(concatenation) }) – in other words, it’s a total function, which is nice – and imposes minimal requirements on the read-only argument (&CStr reference rather than CString) while still being efficient by taking ownership of start.