use libc::c_char;
use std::ffi::CString;
use std::convert::From;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PyString {
_inner: CString,
}
impl PyString {
pub unsafe fn from_ptr(ptr: *mut PyString) -> PyString {
if ptr.is_null() {
panic!("trying to deref a null ptr!");
}
*Box::from_raw(ptr)
}
pub unsafe fn from_ptr_to_string(ptr: *mut PyString) -> String {
if ptr.is_null() {
panic!("trying to deref a null ptr!");
}
let pystr = *(Box::from_raw(ptr));
String::from(pystr._inner.to_str().unwrap())
}
pub fn into_raw(self) -> *mut PyString {
Box::into_raw(Box::new(self))
}
pub unsafe fn from_raw(ptr: *const c_char) -> PyString {
PyString {
_inner: CStr::from_ptr(ptr).to_owned(),
}
}
}
impl fmt::Display for PyString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", String::from(self._inner.to_str().unwrap()))
}
}
impl<'a> From<&'a str> for PyString {
fn from(s: &'a str) -> PyString {
PyString {
_inner: CString::new(s).unwrap(),
}
}
}
impl From<String> for PyString {
fn from(s: String) -> PyString {
PyString {
_inner: CString::new(s).unwrap(),
}
}
}
impl From<PyString> for String {
fn from(s: PyString) -> String {
s.to_string()
}
}
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn pystring_free(ptr: *mut PyString) {
if ptr.is_null() {
return;
}
Box::from_raw(ptr);
}
use std::ffi::CStr;
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn pystring_new(ptr: *const c_char) -> *mut PyString {
let pystr = PyString {
_inner: CStr::from_ptr(ptr).to_owned(),
};
pystr.into_raw()
}
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn pystring_get_str(ptr: *mut PyString) -> *const c_char {
let pystr: PyString = PyString::from_ptr(ptr);
pystr._inner.into_raw()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pystring_operations() {
let source = "test string";
let owned_pystr = PyString::from(source).into_raw();
let back_from_py = unsafe { PyString::from_ptr_to_string(owned_pystr) };
assert_eq!(back_from_py, "test string");
{
String::from(source);
}
}
}