{"id":17158082,"url":"https://github.com/vrmiguel/unixstring","last_synced_at":"2025-04-13T13:30:59.009Z","repository":{"id":46431738,"uuid":"416603752","full_name":"vrmiguel/unixstring","owner":"vrmiguel","description":"An FFI-friendly null-terminated byte string","archived":false,"fork":false,"pushed_at":"2022-01-20T01:41:23.000Z","size":119,"stargazers_count":21,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T04:41:30.331Z","etag":null,"topics":["ffi","hacktoberfest","rust","unix"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/unixstring","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vrmiguel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-13T05:40:07.000Z","updated_at":"2023-10-22T08:01:47.000Z","dependencies_parsed_at":"2022-09-10T13:51:00.650Z","dependency_job_id":null,"html_url":"https://github.com/vrmiguel/unixstring","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrmiguel%2Funixstring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrmiguel%2Funixstring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrmiguel%2Funixstring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrmiguel%2Funixstring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vrmiguel","download_url":"https://codeload.github.com/vrmiguel/unixstring/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248720986,"owners_count":21151021,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","hacktoberfest","rust","unix"],"created_at":"2024-10-14T22:10:31.336Z","updated_at":"2025-04-13T13:30:58.631Z","avatar_url":"https://github.com/vrmiguel.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unixstring [![codecov](https://codecov.io/gh/vrmiguel/unixstring/branch/master/graph/badge.svg?token=6rvhsF5Eiq)](https://codecov.io/gh/vrmiguel/unixstring) ![Crates.io](https://img.shields.io/crates/v/unixstring) [![Docs](https://img.shields.io/badge/docs.rs-unixstring-green)](https://docs.rs/unixstring/)\n\n\n`UnixString` is an FFI-friendly null-terminated byte string that may be constructed from a [`String`](https://doc.rust-lang.org/std/string/struct.String.html), a [`CString`](https://doc.rust-lang.org/std/ffi/struct.CString.html), a [`PathBuf`](https://doc.rust-lang.org/std/path/struct.PathBuf.html), an [`OsString`](https://doc.rust-lang.org/std/ffi/struct.OsString.html) or a collection of bytes.\n\n\nAn [`UnixString`](UnixString) can then be converted into a slice of [`CStr`](https://doc.rust-lang.org/std/ffi/struct.CStr.html), [`Path`](https://doc.rust-lang.org/std/path/struct.Path.html) or [`OsStr`](https://doc.rust-lang.org/std/ffi/struct.OsStr.html) in infallible and zero-cost operations.\n\n\n## Why?\n\n`UnixString` aims to be useful in any scenario where you'd like to use FFI (specially with C) on Unix systems.\nIf 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.\n\nThe same is true with `OsString` and `String` because these three types are allowed to have internal zero bytes and are not null-terminated.\n\n\nA `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`.\n\nA `CString` also does not have direct reference conversions to anything but `\u0026[u8]` or `\u0026CStr`, while `UnixString` has those and more (described below).\n\n## Obtaining references from an UnixString\n\n|   Into   |            Function             |                               Notes                               |\n|:--------:|:-------------------------------:|:-----------------------------------------------------------------:|\n| `\u0026CStr`  |     `UnixString::as_c_str`      |                 Available through `AsRef` as well                 |\n| `\u0026Path`  |      `UnixString::as_path`      |                 Available through `AsRef` as well                 |\n|  `\u0026str`  |      `UnixString::as_str`       |     Fails if the bytes of the `UnixString` aren't valid UTF-8     |\n| `\u0026[u8]`  |     `UnixString::as_bytes`      | Returns the bytes of the `UnixString` without the null terminator |\n| `\u0026[u8]`  | `UnixString::as_bytes_with_nul` |  Returns the bytes of the `UnixString` with the null terminator   |\n| `\u0026OsStr` |     `UnixString::as_os_str`     |                 Available through `AsRef` as well                 |\n| `* const c_char` | `UnixString::as_ptr`    |                                                                   |\n\n## Creating an UnixString\n\n|    From    |            Potential failure            | Trait impl |           Function           |\n|:----------:|:---------------------------------------:|:----------:|:----------------------------:|\n| `CString`  |               Infallible                |    From    |  `UnixString::from_cstring`  |\n| `PathBuf`  | Fails if contains an interior zero byte |  TryFrom   |  `UnixString::from_pathbuf`  |\n|  `String`  | Fails if contains an interior zero byte |  TryFrom   |  `UnixString::from_string`   |\n| `Vec\u003cu8\u003e`  | Fails if contains an interior zero byte |  TryFrom   |   `UnixString::from_bytes`   |\n| `OsString` | Fails if contains an interior zero byte |  TryFrom   | `UnixString::from_os_string` |\n| `* const c_char` | Unsafe, see the docs for more info|  None      | `UnixString::from_ptr`       |\n\n## Converting from an UnixString\n\n\n|    Into    |              Function               |                                 Notes                                  |\n|:----------:|:-----------------------------------:|:----------------------------------------------------------------------:|\n| `CString`  |     `UnixString::into_cstring`      |                                                                        |\n| `PathBuf`  |     `UnixString::into_pathbuf`      |                                                                        |\n| `OsString` |    `UnixString::into_os_string`     |                                                                        |\n|  `String`  |      `UnixString::into_string`      |         Fails if the `UnixString`'s bytes are not valid UTF-8          |\n|  `String`  |   `UnixString::into_string_lossy`   |                                                                        |\n|  `String`  |    `UnixString::to_string_lossy`    |         Non-moving version of `UnixString::into_string_lossy`          |\n|  `String`  | `UnixString::into_string_unchecked` | Unsafe: creates a String without checking if the bytes are valid UTF-8 |\n| `Vec\u003cu8\u003e`  |      `UnixString::into_bytes`       |   Returns the bytes of the `UnixString` without the null terminator    |\n| `Vec\u003cu8\u003e`  |  `UnixString::into_bytes_with_nul`  |     Returns the bytes of the `UnixString` with the null terminator     |\n\nAll of the above are also available through `.into()`.\n\n## Examples\n\n### Creating an UnixString with bytes received through FFI\n\n```rust=\nuse libc::{c_char, getcwd};\nuse unixstring::UnixString;\n\nfn main() {\n    const PATH_SIZ: usize = 1024;\n    let mut buf: [c_char; 1024] = [0; 1024];\n\n    let ptr = \u0026mut buf as *mut c_char;\n\n    unsafe { getcwd(ptr, PATH_SIZ) };\n\n    if ptr.is_null() {\n        panic!(\"getcwd failed\");\n    }\n\n    let unix_string = unsafe { UnixString::from_ptr(ptr as *const c_char) };\n\n    assert_eq!(unix_string.as_path(), std::env::current_dir().unwrap())\n}\n\n```\n\n### Using an UnixString to send bytes through FFI\n\n```rust\nuse std::{convert::TryFrom, env};\n\nuse unixstring::UnixString;\n\nfn stat(path: \u0026UnixString) -\u003e std::io::Result\u003clibc::stat\u003e {\n    // Safety: The all-zero byte-pattern is a valid `struct stat`\n    let mut stat_buf = unsafe { std::mem::zeroed() };\n\n    if -1 == unsafe { libc::lstat(path.as_ptr(), \u0026mut stat_buf) } {\n        let io_err = std::io::Error::last_os_error();\n        Err(io_err)\n    } else {\n        Ok(stat_buf)\n    }\n}\n\n\nfn main() -\u003e std::io::Result\u003c()\u003e{\n    for arg in env::args_os().map(UnixString::try_from).flatten() {\n        let stat = stat(\u0026arg)?;\n        \n        let size = stat.st_size;\n\n        println!(\"{} occupies {} bytes.\", arg.as_path().display(), size);\n    }\n\n    Ok(())\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrmiguel%2Funixstring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvrmiguel%2Funixstring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrmiguel%2Funixstring/lists"}