rustypy/pytypes/
pystring.rs1use libc::c_char;
24use std::ffi::CString;
25
26use std::convert::From;
27use std::fmt;
28
29#[derive(Clone, Debug, PartialEq, Eq, Hash)]
33pub struct PyString {
34 _inner: CString,
35}
36
37impl PyString {
38 pub unsafe fn from_ptr(ptr: *mut PyString) -> PyString {
43 if ptr.is_null() {
44 panic!("trying to deref a null ptr!");
45 }
46 *Box::from_raw(ptr)
47 }
48
49 pub unsafe fn from_ptr_to_string(ptr: *mut PyString) -> String {
54 if ptr.is_null() {
55 panic!("trying to deref a null ptr!");
56 }
57 let pystr = *(Box::from_raw(ptr));
58 String::from(pystr._inner.to_str().unwrap())
59 }
60 pub fn into_raw(self) -> *mut PyString {
63 Box::into_raw(Box::new(self))
64 }
65
66 pub unsafe fn from_raw(ptr: *const c_char) -> PyString {
68 PyString {
69 _inner: CStr::from_ptr(ptr).to_owned(),
70 }
71 }
72}
73
74impl fmt::Display for PyString {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 write!(f, "{}", String::from(self._inner.to_str().unwrap()))
77 }
78}
79
80impl<'a> From<&'a str> for PyString {
81 fn from(s: &'a str) -> PyString {
83 PyString {
84 _inner: CString::new(s).unwrap(),
85 }
86 }
87}
88
89impl From<String> for PyString {
90 fn from(s: String) -> PyString {
92 PyString {
93 _inner: CString::new(s).unwrap(),
94 }
95 }
96}
97
98impl From<PyString> for String {
99 fn from(s: PyString) -> String {
100 s.to_string()
101 }
102}
103
104#[doc(hidden)]
106#[no_mangle]
107pub unsafe extern "C" fn pystring_free(ptr: *mut PyString) {
108 if ptr.is_null() {
109 return;
110 }
111 Box::from_raw(ptr);
112}
113
114use std::ffi::CStr;
115#[doc(hidden)]
117#[no_mangle]
118pub unsafe extern "C" fn pystring_new(ptr: *const c_char) -> *mut PyString {
119 let pystr = PyString {
120 _inner: CStr::from_ptr(ptr).to_owned(),
121 };
122 pystr.into_raw()
123}
124
125#[doc(hidden)]
128#[no_mangle]
129pub unsafe extern "C" fn pystring_get_str(ptr: *mut PyString) -> *const c_char {
130 let pystr: PyString = PyString::from_ptr(ptr);
131 pystr._inner.into_raw()
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn pystring_operations() {
140 let source = "test string";
141 let owned_pystr = PyString::from(source).into_raw();
142 let back_from_py = unsafe { PyString::from_ptr_to_string(owned_pystr) };
143 assert_eq!(back_from_py, "test string");
144 {
145 String::from(source);
146 }
147 }
148}