os string handling

This commit is contained in:
nora 2021-10-01 23:56:41 +02:00
parent 34bddb59a6
commit a393fce416
4 changed files with 28 additions and 15 deletions

View file

@ -1,8 +1,3 @@
# badargs
A Rust fully type-safe argument parser without proc-macros
Usability comes after that
oh and it's also not even close to being usable in any way at all so there's that
oh and also 0 dependencies btw
A zero-dependency full type-safe argument parser.

View file

@ -55,9 +55,9 @@ pub fn badargs<S>() -> BadArgs
where
S: IntoSchema,
{
let arg_schema = Schema::create::<S>().expect("Invalid schema!");
let arg_schema = Schema::create::<S>().expect("Invalid schema");
let args = CliArgs::from_args(&arg_schema, std::env::args());
let args = CliArgs::from_args(&arg_schema, std::env::args_os());
match args {
Ok(args) => BadArgs { args },
Err(err) => reporting::report(err),
@ -132,6 +132,7 @@ mod sealed {
mod error {
use crate::schema::SchemaKind;
use std::ffi::OsString;
/// Invalid schema
#[derive(Debug, Clone, Eq, PartialEq)]
@ -149,5 +150,6 @@ mod error {
INan(String),
UNan(String),
CombinedShortWithValue(String),
InvalidUtf8(OsString),
}
}

View file

@ -2,6 +2,7 @@ use crate::error::CallError;
use crate::schema::{Schema, SchemaKind};
use std::any::Any;
use std::collections::HashMap;
use std::ffi::OsString;
type Result<T> = std::result::Result<T, CallError>;
@ -12,10 +13,14 @@ pub(crate) struct CliArgs {
}
impl CliArgs {
pub fn from_args(schema: &Schema, mut args: impl Iterator<Item = String>) -> Result<Self> {
pub fn from_args(schema: &Schema, mut args: impl Iterator<Item = OsString>) -> Result<Self> {
let mut result = Self::default();
while let Some(arg) = args.next() {
let arg = arg
.into_string()
.map_err(|os_str| CallError::InvalidUtf8(os_str))?;
if let Some(long) = arg.strip_prefix("--") {
parse_long(schema, &mut result, long, &mut args)?;
} else if let Some(shorts) = arg.strip_prefix('-') {
@ -47,7 +52,7 @@ fn parse_shorts(
schema: &Schema,
results: &mut CliArgs,
shorts: &str,
args: &mut impl Iterator<Item = String>,
args: &mut impl Iterator<Item = OsString>,
) -> Result<()> {
// there are kinds of short arguments
// single shorts that takes values: `-o main`
@ -88,7 +93,7 @@ fn parse_long(
schema: &Schema,
results: &mut CliArgs,
long: &str,
args: &mut impl Iterator<Item = String>,
args: &mut impl Iterator<Item = OsString>,
) -> Result<()> {
let command = schema
.long(long)
@ -101,19 +106,23 @@ fn parse_value(
kind: SchemaKind,
results: &mut CliArgs,
long: &'static str,
args: &mut impl Iterator<Item = String>,
args: &mut impl Iterator<Item = OsString>,
) -> Result<()> {
match kind {
SchemaKind::String => {
let string = args
.next()
.ok_or_else(|| CallError::ExpectedValue(long.to_string(), kind))?;
.ok_or_else(|| CallError::ExpectedValue(long.to_string(), kind))?
.into_string()
.map_err(|os_str| CallError::InvalidUtf8(os_str))?;
results.insert(long, Box::new(string));
}
SchemaKind::INum => {
let integer = args
.next()
.ok_or_else(|| CallError::ExpectedValue(long.to_string(), kind))?
.into_string()
.map_err(|os_str| CallError::InvalidUtf8(os_str))?
.parse::<isize>()
.map_err(|_| CallError::INan(long.to_string()))?;
results.insert(long, Box::new(integer))
@ -122,6 +131,8 @@ fn parse_value(
let integer = args
.next()
.ok_or_else(|| CallError::ExpectedValue(long.to_string(), kind))?
.into_string()
.map_err(|os_str| CallError::InvalidUtf8(os_str))?
.parse::<usize>()
.map_err(|_| CallError::UNan(long.to_string()))?;
results.insert(long, Box::new(integer))
@ -158,7 +169,11 @@ mod test {
}
fn parse_args(args: &str) -> Result<CliArgs> {
CliArgs::from_args(&schema(), args.split_whitespace().map(|s| s.to_owned()))
CliArgs::from_args(
&schema(),
args.split_whitespace()
.map(|s| OsString::from(s.to_owned())),
)
}
#[test]

View file

@ -19,7 +19,8 @@ pub fn report(err: CallError) -> ! {
}
CallError::INan(arg) => println!("error: argument '{}' expected a positive integer value, but got an invalid positive integer.", arg),
CallError::UNan(arg) => println!("error: argument '{}' expected an integer value, but got an invalid integer.", arg),
CallError::CombinedShortWithValue(arg) => println!("error: using argument expecting value '{}' in position where only flags are allowed", arg)
CallError::CombinedShortWithValue(arg) => println!("error: using argument expecting value '{}' in position where only flags are allowed", arg),
CallError::InvalidUtf8(os_str) => println!("error: invalid utf8: '{}'", os_str.to_string_lossy()),
}
std::process::exit(1)