use std::{
borrow::Cow,
collections::HashMap,
ffi::{OsStr, OsString},
iter::Map,
slice::Iter,
};
use crate::{
args::{MatchedArg, SubCommand},
INVALID_UTF8,
};
#[derive(Debug, Clone)]
pub struct ArgMatches<'a> {
#[doc(hidden)]
pub args: HashMap<&'a str, MatchedArg>,
#[doc(hidden)]
pub subcommand: Option<Box<SubCommand<'a>>>,
#[doc(hidden)]
pub usage: Option<String>,
}
impl<'a> Default for ArgMatches<'a> {
fn default() -> Self {
ArgMatches {
args: HashMap::new(),
subcommand: None,
usage: None,
}
}
}
impl<'a> ArgMatches<'a> {
#[doc(hidden)]
pub fn new() -> Self {
ArgMatches {
..Default::default()
}
}
pub fn value_of<S: AsRef<str>>(&self, name: S) -> Option<&str> {
if let Some(arg) = self.args.get(name.as_ref()) {
if let Some(v) = arg.vals.get(0) {
return Some(v.to_str().expect(INVALID_UTF8));
}
}
None
}
#[cfg_attr(not(unix), doc = " ```ignore")]
#[cfg_attr(unix, doc = " ```")]
pub fn value_of_lossy<S: AsRef<str>>(&'a self, name: S) -> Option<Cow<'a, str>> {
if let Some(arg) = self.args.get(name.as_ref()) {
if let Some(v) = arg.vals.get(0) {
return Some(v.to_string_lossy());
}
}
None
}
#[cfg_attr(not(unix), doc = " ```ignore")]
#[cfg_attr(unix, doc = " ```")]
pub fn value_of_os<S: AsRef<str>>(&self, name: S) -> Option<&OsStr> {
self.args
.get(name.as_ref())
.and_then(|arg| arg.vals.get(0).map(|v| v.as_os_str()))
}
pub fn values_of<S: AsRef<str>>(&'a self, name: S) -> Option<Values<'a>> {
if let Some(arg) = self.args.get(name.as_ref()) {
fn to_str_slice(o: &OsString) -> &str {
o.to_str().expect(INVALID_UTF8)
}
let to_str_slice: fn(&OsString) -> &str = to_str_slice; return Some(Values {
iter: arg.vals.iter().map(to_str_slice),
});
}
None
}
#[cfg_attr(not(unix), doc = " ```ignore")]
#[cfg_attr(unix, doc = " ```")]
pub fn values_of_lossy<S: AsRef<str>>(&'a self, name: S) -> Option<Vec<String>> {
if let Some(arg) = self.args.get(name.as_ref()) {
return Some(
arg.vals
.iter()
.map(|v| v.to_string_lossy().into_owned())
.collect(),
);
}
None
}
#[cfg_attr(not(unix), doc = " ```ignore")]
#[cfg_attr(unix, doc = " ```")]
pub fn values_of_os<S: AsRef<str>>(&'a self, name: S) -> Option<OsValues<'a>> {
fn to_str_slice(o: &OsString) -> &OsStr {
&*o
}
let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; if let Some(arg) = self.args.get(name.as_ref()) {
return Some(OsValues {
iter: arg.vals.iter().map(to_str_slice),
});
}
None
}
pub fn is_present<S: AsRef<str>>(&self, name: S) -> bool {
if let Some(ref sc) = self.subcommand {
if sc.name == name.as_ref() {
return true;
}
}
self.args.contains_key(name.as_ref())
}
pub fn occurrences_of<S: AsRef<str>>(&self, name: S) -> u64 {
self.args.get(name.as_ref()).map_or(0, |a| a.occurs)
}
pub fn index_of<S: AsRef<str>>(&self, name: S) -> Option<usize> {
if let Some(arg) = self.args.get(name.as_ref()) {
if let Some(i) = arg.indices.get(0) {
return Some(*i);
}
}
None
}
pub fn indices_of<S: AsRef<str>>(&'a self, name: S) -> Option<Indices<'a>> {
if let Some(arg) = self.args.get(name.as_ref()) {
fn to_usize(i: &usize) -> usize {
*i
}
let to_usize: fn(&usize) -> usize = to_usize; return Some(Indices {
iter: arg.indices.iter().map(to_usize),
});
}
None
}
pub fn subcommand_matches<S: AsRef<str>>(&self, name: S) -> Option<&ArgMatches<'a>> {
if let Some(ref s) = self.subcommand {
if s.name == name.as_ref() {
return Some(&s.matches);
}
}
None
}
pub fn subcommand_name(&self) -> Option<&str> {
self.subcommand.as_ref().map(|sc| &sc.name[..])
}
pub fn subcommand(&self) -> (&str, Option<&ArgMatches<'a>>) {
self.subcommand
.as_ref()
.map_or(("", None), |sc| (&sc.name[..], Some(&sc.matches)))
}
pub fn usage(&self) -> &str {
self.usage.as_ref().map_or("", |u| &u[..])
}
}
#[derive(Debug, Clone)]
pub struct Values<'a> {
iter: Map<Iter<'a, OsString>, fn(&'a OsString) -> &'a str>,
}
impl<'a> Iterator for Values<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> DoubleEndedIterator for Values<'a> {
fn next_back(&mut self) -> Option<&'a str> {
self.iter.next_back()
}
}
impl<'a> ExactSizeIterator for Values<'a> {}
impl<'a> Default for Values<'a> {
fn default() -> Self {
static EMPTY: [OsString; 0] = [];
fn to_str_slice(_: &OsString) -> &str {
unreachable!()
}
Values {
iter: EMPTY[..].iter().map(to_str_slice),
}
}
}
#[cfg_attr(not(unix), doc = " ```ignore")]
#[cfg_attr(unix, doc = " ```")]
#[derive(Debug, Clone)]
pub struct OsValues<'a> {
iter: Map<Iter<'a, OsString>, fn(&'a OsString) -> &'a OsStr>,
}
impl<'a> Iterator for OsValues<'a> {
type Item = &'a OsStr;
fn next(&mut self) -> Option<&'a OsStr> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> DoubleEndedIterator for OsValues<'a> {
fn next_back(&mut self) -> Option<&'a OsStr> {
self.iter.next_back()
}
}
impl<'a> ExactSizeIterator for OsValues<'a> {}
impl<'a> Default for OsValues<'a> {
fn default() -> Self {
static EMPTY: [OsString; 0] = [];
fn to_str_slice(_: &OsString) -> &OsStr {
unreachable!()
}
OsValues {
iter: EMPTY[..].iter().map(to_str_slice),
}
}
}
#[derive(Debug, Clone)]
pub struct Indices<'a> {
iter: Map<Iter<'a, usize>, fn(&'a usize) -> usize>,
}
impl<'a> Iterator for Indices<'a> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> DoubleEndedIterator for Indices<'a> {
fn next_back(&mut self) -> Option<usize> {
self.iter.next_back()
}
}
impl<'a> ExactSizeIterator for Indices<'a> {}
impl<'a> Default for Indices<'a> {
fn default() -> Self {
static EMPTY: [usize; 0] = [];
fn to_usize(_: &usize) -> usize {
unreachable!()
}
Indices {
iter: EMPTY[..].iter().map(to_usize),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_values() {
let mut values: Values = Values::default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_values_with_shorter_lifetime() {
let matches = ArgMatches::new();
let mut values = matches.values_of("").unwrap_or_default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_osvalues() {
let mut values: OsValues = OsValues::default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_osvalues_with_shorter_lifetime() {
let matches = ArgMatches::new();
let mut values = matches.values_of_os("").unwrap_or_default();
assert_eq!(values.next(), None);
}
#[test]
fn test_default_indices() {
let mut indices: Indices = Indices::default();
assert_eq!(indices.next(), None);
}
#[test]
fn test_default_indices_with_shorter_lifetime() {
let matches = ArgMatches::new();
let mut indices = matches.indices_of("").unwrap_or_default();
assert_eq!(indices.next(), None);
}
}