1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use std::ffi::CString; use std::mem::forget; use libc; /// Compatibility wrapper for strings allocated in Rust and passed to C. /// /// Rust doesn't ensure the safety of freeing memory across an FFI boundary, so /// we need to take special care to ensure we're not accidentally calling /// `tor_free`() on any string allocated in Rust. To more easily differentiate /// between strings that possibly (if Rust support is enabled) were allocated /// in Rust, C has the `rust_str_t` helper type. The equivalent on the Rust /// side is `RustString`. /// /// Note: This type must not be used for strings allocated in C. #[repr(C)] #[derive(Debug)] pub struct RustString(*mut libc::c_char); impl RustString { /// Returns a pointer to the underlying NUL-terminated byte array. /// /// Note that this function is not typically useful for Rust callers, /// except in a direct FFI context. /// /// # Examples /// ``` /// # use tor_util::RustString; /// use std::ffi::CString; /// /// let r = RustString::from(CString::new("asdf").unwrap()); /// let c_str = r.as_ptr(); /// assert_eq!(b'a', unsafe { *c_str as u8}); /// ``` pub fn as_ptr(&self) -> *const libc::c_char { self.0 as *const libc::c_char } } impl From<CString> for RustString { /// Constructs a new `RustString` /// /// # Examples /// ``` /// # use tor_util::RustString; /// use std::ffi::CString; /// /// let r = RustString::from(CString::new("asdf").unwrap()); /// ``` fn from(str: CString) -> RustString { RustString(str.into_raw()) } } impl Into<CString> for RustString { /// Reconstructs a `CString` from this `RustString`. /// /// Useful to take ownership back from a `RustString` that was given to C /// code. /// /// # Examples /// ``` /// # use tor_util::RustString; /// use std::ffi::CString; /// /// let cs = CString::new("asdf").unwrap(); /// let r = RustString::from(cs.clone()); /// let cs2 = r.into(); /// assert_eq!(cs, cs2); /// ``` fn into(self) -> CString { // Calling from_raw is always OK here: We only construct self using // valid CStrings and don't expose anything that could mutate it let ret = unsafe { CString::from_raw(self.0) }; forget(self); ret } } impl Drop for RustString { fn drop(&mut self) { // Don't use into() here, because we would need to move out of // self. Same safety consideration. Immediately drop the created // CString, which takes care of freeing the wrapped string. unsafe { CString::from_raw(self.0) }; } } #[cfg(test)] mod test { use std::mem; use super::*; /// Ensures we're not adding overhead by using RustString. #[test] fn size_of() { assert_eq!(mem::size_of::<*mut libc::c_char>(), mem::size_of::<RustString>()) } }