-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathstringutils.rs
More file actions
85 lines (74 loc) · 2.24 KB
/
stringutils.rs
File metadata and controls
85 lines (74 loc) · 2.24 KB
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
use crate::errors::Result;
use crate::sys::ffgerr;
use libc::{c_char, c_int, size_t};
use std::ffi::{CStr, CString};
/// Helper function converting a C string buffer to Rust String
pub fn buf_to_string(buffer: &[c_char]) -> Result<String> {
// Safety: c_char and u8 have the same size and alignment
let bytes: &[u8] = unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len()) };
let c_str = CStr::from_bytes_until_nul(bytes)
.map_err(|_| crate::errors::Error::Message("buffer is not null-terminated".to_string()))?;
Ok(c_str.to_str()?.to_string())
}
#[repr(C)]
pub struct StringList {
pub len: size_t,
cap: size_t,
mem: Vec<*mut c_char>,
}
impl StringList {
pub fn from_slice(stringvec: &[String]) -> Result<Self> {
let converted: Vec<*mut c_char> = stringvec
.iter()
.map(|x| CString::new(x.clone()).unwrap().into_raw())
.collect();
let listlen = converted.len();
let listcap = converted.capacity();
let stringlist = StringList {
len: listlen,
cap: listcap,
mem: converted,
};
Ok(stringlist)
}
pub fn as_ptr(&self) -> *mut *mut c_char {
self.mem.as_slice().as_ptr() as *mut _
}
}
impl Drop for StringList {
// TODO: IS THIS SOUND?
// Free the memory of this string list
fn drop(&mut self) {
for ptr in &self.mem {
if ptr.is_null() {
continue;
}
let _ = unsafe { CString::from_raw(*ptr) };
}
}
}
/// Internal function to get the fits error description from a status code
pub fn status_to_string(status: c_int) -> Result<Option<String>> {
match status {
0 => Ok(None),
status => {
let mut buffer: Vec<c_char> = vec![0; 31];
unsafe {
ffgerr(status, buffer.as_mut_ptr());
}
let result_str = buf_to_string(&buffer)?;
Ok(Some(result_str))
}
}
}
#[cfg(test)]
mod test {
use super::status_to_string;
#[test]
fn test_returning_error_messages() {
assert_eq!(
status_to_string(105).unwrap().unwrap(),
"couldn't create the named file"
);
}
}