UnixString is An FFI-friendly null-terminated byte string

Overview

unixstring codecov Crates.io Docs

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 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 UnixString::into_bytes Returns the bytes of the UnixString without the null terminator
Vec 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
    {
    
   // 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(())
}
  
You might also like...
A user-friendly TUI client for Matrix written in Rust!

Konoha A user-friendly TUI client for Matrix written in Rust! Notice: The client is currently not usable and is only hosted on GitHub for version cont

Grep with human-friendly search output
Grep with human-friendly search output

hgrep: Human-friendly GREP hgrep is a grep tool to search files with given pattern and print the matched code snippets with human-friendly syntax high

A simple, human-friendly, embeddable scripting language

Mica Language reference · Rust API A simple, human-friendly scripting language, developed one feature at a time. Human-friendly syntax inspired by Rub

A user-friendly TUI for secure file transfers, with arrow-key and VIM-style navigation
A user-friendly TUI for secure file transfers, with arrow-key and VIM-style navigation

gsftp SFTP with an interactive text-based user interface (TUI). Transfer files through an encrypted connection with a visual interface, so you can see

A user-friendly re-implementation of existing hex tools in Rust
A user-friendly re-implementation of existing hex tools in Rust

Hex A project to create alternate (and more user friendly) versions of existing hex tools. The project can be installed as a extension to the github-c

OSINT from your favorite services in a friendly terminal user interface
OSINT from your favorite services in a friendly terminal user interface

osintui Open Source Intelligence Terminal User Interface Report Bug · Request Feature Installation First, install Rust (using the recommended rustup i

Simple low-level web server to serve file uploads with some shell scripting-friendly features

http_file_uploader Simple low-level web server to serve file uploads with some shell scripting-friendly features. A bridge between Web's multipart/for

Pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way.

DNG-rs   A pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way. Also containing code for re

Friendly symbol notation.

symmie Friendly symbol notation. The goal of this project is to provide a systematic notation for technical symbols and emoji. The notation consist of

Comments
  • Create std::fs::File from UnixString without allocating

    Create std::fs::File from UnixString without allocating

    When opening a std::fs::File in Rust on Linux right now, you give it an AsRef<Path>, which is turned into a CString, reallocating the string in the process (rust/library/std/src/sys/unix/fs.rs, function cstr()). There is no way to use safe rust and just the standard library to open a File without allocating a String on the heap. Even using this library to convert a UnixString into a Path to open a File, the standard library has no knowledge that the UnixString was nul terminated, so must reallocate.

    It would be nice if this library (or one based on it) gave that capability. A File::open<P:AsRef<UnixStr>> that is guaranteed to not allocate in the success case; the error case might allocate an String to describe the error.

    Also you may have noticed I included a signature with UnixStr. I think it makes sense to have separate UnixString and UnixStr (owned vs borrowed) just like the standard library has for String vs str, CString vs CStr, OsString vs OsStr, etc.

    opened by maxbla 0
Owner
Vinícius Miguel
barely passed the Turing test
Vinícius Miguel
`rusty_regex` takes an input string and produces a `regex` string representing what was provided.

rusty_regex This project provides a binary that takes an input string, and preps it for regex usage, effectively replacing known generics and producin

Chris Speakes 2 Dec 31, 2022
decode a byte stream of varint length-encoded messages into a stream of chunks

length-prefixed-stream decode a byte stream of varint length-encoded messages into a stream of chunks This crate is similar to and compatible with the

James Halliday 4 Feb 26, 2022
BearLibTerminal FFI for Rust

BearLibTerminal.rs BearLibTerminal FFI for Rust. Requirements You need to compile/get a precompiled version of BearLibTerminal yourself and put it som

наб 30 Jul 25, 2022
Unopinionated low level API bindings focused on soundness, safety, and stronger types over raw FFI.

?? firehazard ?? Create a fire hazard by locking down your (Microsoft) Windows so nobody can escape (your security sandbox.) Unopinionated low level A

null 5 Nov 17, 2022
Nostr protocol implementation, SDK and FFI

Searchnos: an experimental implementation of NIP-50 This is a relay-like bridge server that provides a Nostr full-text search capability by using Elas

SAGE 8 Jul 2, 2023
Chemical structure generation for protein sequences as SMILES string.

proteinogenic Chemical structure generation for protein sequences as SMILES string. ?? Usage This crate builds on top of purr, a crate providing primi

Martin Larralde 4 Aug 4, 2022
`matchable` provides a convenient enum for checking if a piece of text is matching a string or a regex.

matchable matchable provides a convenient enum for checking if a piece of text is matching a string or a regex. The common usage of this crate is used

Pig Fang 6 Dec 19, 2022
⚡️Highly efficient data and string formatting library for Rust.

⚡️Highly efficient data and string formatting library for Rust. ?? Overview Pad and format string slices and generic vectors efficiently with minimal

Firelink Data 3 Dec 21, 2023
This is choose, a human-friendly and fast alternative to cut and (sometimes) awk

Choose This is choose, a human-friendly and fast alternative to cut and (sometimes) awk Features terse field selection syntax similar to Python's list

Ryan Geary 1.4k Jan 7, 2023
fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find

fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find. While it does not aim to support all of find's powerful functionality, it provides sensible (opinionated) defaults for a majority of use cases.

David Peter 25.9k Jan 9, 2023