mirror of
https://github.com/Noratrieb/badargs.git
synced 2026-01-16 04:35:06 +01:00
os string handling
This commit is contained in:
parent
34bddb59a6
commit
a393fce416
4 changed files with 28 additions and 15 deletions
|
|
@ -1,8 +1,3 @@
|
||||||
# badargs
|
# badargs
|
||||||
A Rust fully type-safe argument parser without proc-macros
|
|
||||||
|
|
||||||
Usability comes after that
|
A zero-dependency full type-safe argument parser.
|
||||||
|
|
||||||
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
|
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,9 @@ pub fn badargs<S>() -> BadArgs
|
||||||
where
|
where
|
||||||
S: IntoSchema,
|
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 {
|
match args {
|
||||||
Ok(args) => BadArgs { args },
|
Ok(args) => BadArgs { args },
|
||||||
Err(err) => reporting::report(err),
|
Err(err) => reporting::report(err),
|
||||||
|
|
@ -132,6 +132,7 @@ mod sealed {
|
||||||
|
|
||||||
mod error {
|
mod error {
|
||||||
use crate::schema::SchemaKind;
|
use crate::schema::SchemaKind;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
|
||||||
/// Invalid schema
|
/// Invalid schema
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
|
@ -149,5 +150,6 @@ mod error {
|
||||||
INan(String),
|
INan(String),
|
||||||
UNan(String),
|
UNan(String),
|
||||||
CombinedShortWithValue(String),
|
CombinedShortWithValue(String),
|
||||||
|
InvalidUtf8(OsString),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
src/parse.rs
27
src/parse.rs
|
|
@ -2,6 +2,7 @@ use crate::error::CallError;
|
||||||
use crate::schema::{Schema, SchemaKind};
|
use crate::schema::{Schema, SchemaKind};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, CallError>;
|
type Result<T> = std::result::Result<T, CallError>;
|
||||||
|
|
||||||
|
|
@ -12,10 +13,14 @@ pub(crate) struct CliArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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();
|
let mut result = Self::default();
|
||||||
|
|
||||||
while let Some(arg) = args.next() {
|
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("--") {
|
if let Some(long) = arg.strip_prefix("--") {
|
||||||
parse_long(schema, &mut result, long, &mut args)?;
|
parse_long(schema, &mut result, long, &mut args)?;
|
||||||
} else if let Some(shorts) = arg.strip_prefix('-') {
|
} else if let Some(shorts) = arg.strip_prefix('-') {
|
||||||
|
|
@ -47,7 +52,7 @@ fn parse_shorts(
|
||||||
schema: &Schema,
|
schema: &Schema,
|
||||||
results: &mut CliArgs,
|
results: &mut CliArgs,
|
||||||
shorts: &str,
|
shorts: &str,
|
||||||
args: &mut impl Iterator<Item = String>,
|
args: &mut impl Iterator<Item = OsString>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// there are kinds of short arguments
|
// there are kinds of short arguments
|
||||||
// single shorts that takes values: `-o main`
|
// single shorts that takes values: `-o main`
|
||||||
|
|
@ -88,7 +93,7 @@ fn parse_long(
|
||||||
schema: &Schema,
|
schema: &Schema,
|
||||||
results: &mut CliArgs,
|
results: &mut CliArgs,
|
||||||
long: &str,
|
long: &str,
|
||||||
args: &mut impl Iterator<Item = String>,
|
args: &mut impl Iterator<Item = OsString>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let command = schema
|
let command = schema
|
||||||
.long(long)
|
.long(long)
|
||||||
|
|
@ -101,19 +106,23 @@ fn parse_value(
|
||||||
kind: SchemaKind,
|
kind: SchemaKind,
|
||||||
results: &mut CliArgs,
|
results: &mut CliArgs,
|
||||||
long: &'static str,
|
long: &'static str,
|
||||||
args: &mut impl Iterator<Item = String>,
|
args: &mut impl Iterator<Item = OsString>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match kind {
|
match kind {
|
||||||
SchemaKind::String => {
|
SchemaKind::String => {
|
||||||
let string = args
|
let string = args
|
||||||
.next()
|
.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));
|
results.insert(long, Box::new(string));
|
||||||
}
|
}
|
||||||
SchemaKind::INum => {
|
SchemaKind::INum => {
|
||||||
let integer = args
|
let integer = args
|
||||||
.next()
|
.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))?
|
||||||
.parse::<isize>()
|
.parse::<isize>()
|
||||||
.map_err(|_| CallError::INan(long.to_string()))?;
|
.map_err(|_| CallError::INan(long.to_string()))?;
|
||||||
results.insert(long, Box::new(integer))
|
results.insert(long, Box::new(integer))
|
||||||
|
|
@ -122,6 +131,8 @@ fn parse_value(
|
||||||
let integer = args
|
let integer = args
|
||||||
.next()
|
.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))?
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
.map_err(|_| CallError::UNan(long.to_string()))?;
|
.map_err(|_| CallError::UNan(long.to_string()))?;
|
||||||
results.insert(long, Box::new(integer))
|
results.insert(long, Box::new(integer))
|
||||||
|
|
@ -158,7 +169,11 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_args(args: &str) -> Result<CliArgs> {
|
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]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -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::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::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)
|
std::process::exit(1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue