9 releases
0.2.7 | Jan 20, 2022 |
---|---|
0.2.6 | Oct 18, 2021 |
0.1.0 | Oct 13, 2021 |
#385 in Unix APIs
22 downloads per month
Used in stromatekt
43KB
383 lines
unixstring
UnixString
is an FFI-friendly null-terminated byte string that may be constructed from a String
, a CString
, a PathBuf
, an OsString
or a collection of bytes.
An UnixString
can then be converted into a slice of CStr
, Path
or OsStr
in infallible and zero-cost operations.
Why?
UnixString
aims to be useful in any scenario where you'd like to use FFI (specially with C) on Unix systems.
If you have a PathBuf
, for example, you can send that data to a libc
function, such as stat
, but you'd have to first allocate a CString
(or something analogous) to do so.
The same is true with OsString
and String
because these three types are allowed to have internal zero bytes and are not null-terminated.
A UnixString
is very close to what a CString
is but with increased flexibility and usability. A CString
cannot be changed or increased after instantited, while UnixString
is growable through its push
and push_bytes
methods, somewhat similar to OsString
.
A CString
also does not have direct reference conversions to anything but &[u8]
or &CStr
, while UnixString
has those and more (described below).
Obtaining references from an UnixString
Into | Function | Notes |
---|---|---|
&CStr |
UnixString::as_c_str |
Available through AsRef as well |
&Path |
UnixString::as_path |
Available through AsRef as well |
&str |
UnixString::as_str |
Fails if the bytes of the UnixString aren't valid UTF-8 |
&[u8] |
UnixString::as_bytes |
Returns the bytes of the UnixString without the null terminator |
&[u8] |
UnixString::as_bytes_with_nul |
Returns the bytes of the UnixString with the null terminator |
&OsStr |
UnixString::as_os_str |
Available through AsRef as well |
* const c_char |
UnixString::as_ptr |
Creating an UnixString
From | Potential failure | Trait impl | Function |
---|---|---|---|
CString |
Infallible | From | UnixString::from_cstring |
PathBuf |
Fails if contains an interior zero byte | TryFrom | UnixString::from_pathbuf |
String |
Fails if contains an interior zero byte | TryFrom | UnixString::from_string |
Vec<u8> |
Fails if contains an interior zero byte | TryFrom | UnixString::from_bytes |
OsString |
Fails if contains an interior zero byte | TryFrom | UnixString::from_os_string |
* const c_char |
Unsafe, see the docs for more info | None | UnixString::from_ptr |
Converting from an UnixString
Into | Function | Notes |
---|---|---|
CString |
UnixString::into_cstring |
|
PathBuf |
UnixString::into_pathbuf |
|
OsString |
UnixString::into_os_string |
|
String |
UnixString::into_string |
Fails if the UnixString 's bytes are not valid UTF-8 |
String |
UnixString::into_string_lossy |
|
String |
UnixString::to_string_lossy |
Non-moving version of UnixString::into_string_lossy |
String |
UnixString::into_string_unchecked |
Unsafe: creates a String without checking if the bytes are valid UTF-8 |
Vec<u8> |
UnixString::into_bytes |
Returns the bytes of the UnixString without the null terminator |
Vec<u8> |
UnixString::into_bytes_with_nul |
Returns the bytes of the UnixString with the null terminator |
All of the above are also available through .into()
.
Examples
Creating an UnixString with bytes received through FFI
use libc::{c_char, getcwd};
use unixstring::UnixString;
fn main() {
const PATH_SIZ: usize = 1024;
let mut buf: [c_char; 1024] = [0; 1024];
let ptr = &mut buf as *mut c_char;
unsafe { getcwd(ptr, PATH_SIZ) };
if ptr.is_null() {
panic!("getcwd failed");
}
let unix_string = unsafe { UnixString::from_ptr(ptr as *const c_char) };
assert_eq!(unix_string.as_path(), std::env::current_dir().unwrap())
}
Using an UnixString to send bytes through FFI
use std::{convert::TryFrom, env};
use unixstring::UnixString;
fn stat(path: &UnixString) -> std::io::Result<libc::stat> {
// Safety: The all-zero byte-pattern is a valid `struct stat`
let mut stat_buf = unsafe { std::mem::zeroed() };
if -1 == unsafe { libc::lstat(path.as_ptr(), &mut stat_buf) } {
let io_err = std::io::Error::last_os_error();
Err(io_err)
} else {
Ok(stat_buf)
}
}
fn main() -> std::io::Result<()>{
for arg in env::args_os().map(UnixString::try_from).flatten() {
let stat = stat(&arg)?;
let size = stat.st_size;
println!("{} occupies {} bytes.", arg.as_path().display(), size);
}
Ok(())
}
Dependencies
~44KB