Make argh directly parse into Utf8CString

This commit is contained in:
topjohnwu
2025-08-26 23:37:16 -07:00
committed by John Wu
parent ea72666df8
commit 3599dcedfb
7 changed files with 95 additions and 116 deletions

View File

@@ -7,7 +7,7 @@ use std::fmt::{Debug, Display, Formatter, Write};
use std::ops::Deref;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::str::{FromStr, Utf8Error};
use std::{fmt, mem, slice, str};
use thiserror::Error;
@@ -200,7 +200,18 @@ impl From<String> for Utf8CString {
impl From<&str> for Utf8CString {
fn from(value: &str) -> Self {
value.to_string().into()
let mut s = String::with_capacity(value.len() + 1);
s.push_str(value);
s.nul_terminate();
Utf8CString(s)
}
}
impl FromStr for Utf8CString {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}

View File

@@ -1,4 +1,4 @@
use crate::{Utf8CStr, cstr, ffi};
use crate::{Utf8CStr, Utf8CString, cstr, ffi};
use argh::{EarlyExit, MissingRequirements};
use libc::c_char;
use std::{
@@ -105,9 +105,9 @@ impl<T> EarlyExitExt<T> for Result<T, EarlyExit> {
pub struct PositionalArgParser<'a>(pub slice::Iter<'a, &'a str>);
impl PositionalArgParser<'_> {
pub fn required(&mut self, field_name: &'static str) -> Result<String, EarlyExit> {
pub fn required(&mut self, field_name: &'static str) -> Result<Utf8CString, EarlyExit> {
if let Some(next) = self.0.next() {
Ok(next.to_string())
Ok((*next).into())
} else {
let mut missing = MissingRequirements::default();
missing.missing_positional_arg(field_name);
@@ -116,17 +116,17 @@ impl PositionalArgParser<'_> {
}
}
pub fn optional(&mut self) -> Option<String> {
self.0.next().map(ToString::to_string)
pub fn optional(&mut self) -> Option<Utf8CString> {
self.0.next().map(|s| (*s).into())
}
pub fn last_required(&mut self, field_name: &'static str) -> Result<String, EarlyExit> {
pub fn last_required(&mut self, field_name: &'static str) -> Result<Utf8CString, EarlyExit> {
let r = self.required(field_name)?;
self.ensure_end()?;
Ok(r)
}
pub fn last_optional(&mut self) -> Result<Option<String>, EarlyExit> {
pub fn last_optional(&mut self) -> Result<Option<Utf8CString>, EarlyExit> {
let r = self.optional();
if r.is_none() {
return Ok(r);