| Crates.io | snailx |
| lib.rs | snailx |
| version | 0.8.3 |
| created_at | 2025-10-01 21:21:00.833282+00 |
| updated_at | 2025-11-04 20:51:13.477184+00 |
| description | Zero-allocation, low-overhead access to program arguments (argv) with iterators over `&'static CStr`, `&'static str`, and `&'static OsStr`. Works in no_std (optional std feature) and targets Unix and macOS. |
| homepage | |
| repository | https://github.com/echohumm/snail |
| max_upload_size | |
| id | 1863515 |
| size | 164,385 |
snailx provides a simple, zero-allocation, zero-dependency API for iterating over program arguments on Unix and MacOS.
std::env::args(), but optimization is in its early stages.use snailx::Args;
fn main() {
// Iterate over arguments, skipping the first one.
// Because `snailx` uses its own, minimal and intermediary `CStr` type, it must be converted to a `std::ffi::CStr`
// before usage. This behavior is planned to be improved in the future.
let args = Args::new().skip(1).filter_map(|arg| arg.to_stdlib().to_str().ok());
match args.next() {
Some("run") => println!("Running"),
Some("build") => println!("Building"),
Some(_) => println!("Unknown subcommand"),
None => println!("No subcommand provided"),
}
}
no_std support technicallysnailx iterators to be at least twice as fast as std::env::args(),
but you should benchmark yourself. In certain cases, snailx is up to 6x faster than stdlib, but much slower in
others.Args::new() -> Args - The basic iterator over the program arguments as snailx::CStr<'static>MappedArgs::osstr() -> MappedArgs<&'static OsStr, fn(*const u8) -> Option<&'static std::ffi::OsStr> - Iterator over
the program arguments as &'static std::ffi::OsStrMappedArgs::utf8() -> MappedArgs<&'static str, fn(*const u8) -> Option<&'static str> - Iterator over the program
arguments as &'static strMappedArgs::new<T, F: Fn(*const u8) -> Option<T>>(map: F) - Iterator over the program arguments as Tdirect::argc_argv() -> (u32, *const *const u8) - Raw access to (argc, argv)std - Enables the std feature, which enables all functions relating to OsStr and is one way to enable
snailx::CStr::to_stdlibno_cold - Removes the #[cold] attribute from several functionsto_core_cstr (MSRV 1.64.0) - Enables snailx::CStr::to_stdlibassume_valid_str - This massively speeds up the iterator returned by MappedArgs::utf8() by disabling validity
checks, but can cause UB if the program arguments are invalid UTF-8. Use disrecommended unless you can guarantee the
returned &'static strs will be used safely or invalid UTF-8 will never be used.Args - Iterator over program arguments as snailx::CStr<'static>MappedArgs<T, F> - Generic iterator that applies a mapping function to each argumentCStr<'static> - Minimal C-style string type for zero-allocation argument access. This exists because this crate is
no_std, but core_cstr was stabilized after its MSRV.snailx works on both in theory but is tested with glibc.snailx uses unsafe code to access OS-provided argument storage. The safety guarantees are:
assume_valid_str is enabledassume_valid_str feature trades safety for performance and should only be used when you can guarantee valid
UTF-8 inputuse snailx::Args;
fn main() {
for (i, arg) in Args::new().enumerate() {
println!("Argument {}: {:?}", i, arg);
}
}
use snailx::MappedArgs;
fn main() {
for arg in MappedArgs::utf8() {
match arg {
"help" => println!("Usage: ..."),
"version" => println!("Version 0.1.0"),
other => println!("Unknown argument: {}", other),
}
}
}
use snailx::MappedArgs;
fn main() {
// alternatively, if `infallible_map` is enabled, you can use `MappedArgs::new_infallible()` if you want
// `size_hint` to return an accurate lower bound.
let lengths: Vec<usize> = MappedArgs::new(|ptr| {
unsafe {
// simple strlen implementation
let mut i = 0;
while ptr.add(i) != 0 {
i += 1;
}
Some(i)
}
}).collect();
println!("Argument lengths: {:?}", lengths);
}
use snailx::indexing_parser::{IndexingParser, OptRule};
fn main() {
let mut parser = Parser::new();
parser.parse(&[
OptRule::new_auto("number")
]);
if let Some(num) = parser.option("number").and_then(|num_vals| num_vals.next()).and_then(|num_str| num_str.parse::<u64>()) {
// do something with the number
for i in 0..num {
println!("{}", i);
}
} else {
eprintln!("You must specify the value of `number`!");
}
}
See CONTRIBUTING.md
snailx is dual licensed under GPLv3 and MIT.