119625d8cSopenharmony_ci// Std 219625d8cSopenharmony_ciuse std::{ 319625d8cSopenharmony_ci ffi::{OsStr, OsString}, 419625d8cSopenharmony_ci iter::{Cloned, Flatten}, 519625d8cSopenharmony_ci slice::Iter, 619625d8cSopenharmony_ci}; 719625d8cSopenharmony_ci 819625d8cSopenharmony_ciuse crate::builder::ArgPredicate; 919625d8cSopenharmony_ciuse crate::parser::AnyValue; 1019625d8cSopenharmony_ciuse crate::parser::AnyValueId; 1119625d8cSopenharmony_ciuse crate::parser::ValueSource; 1219625d8cSopenharmony_ciuse crate::util::eq_ignore_case; 1319625d8cSopenharmony_ciuse crate::INTERNAL_ERROR_MSG; 1419625d8cSopenharmony_ci 1519625d8cSopenharmony_ci#[derive(Debug, Clone)] 1619625d8cSopenharmony_cipub(crate) struct MatchedArg { 1719625d8cSopenharmony_ci source: Option<ValueSource>, 1819625d8cSopenharmony_ci indices: Vec<usize>, 1919625d8cSopenharmony_ci type_id: Option<AnyValueId>, 2019625d8cSopenharmony_ci vals: Vec<Vec<AnyValue>>, 2119625d8cSopenharmony_ci raw_vals: Vec<Vec<OsString>>, 2219625d8cSopenharmony_ci ignore_case: bool, 2319625d8cSopenharmony_ci} 2419625d8cSopenharmony_ci 2519625d8cSopenharmony_ciimpl MatchedArg { 2619625d8cSopenharmony_ci pub(crate) fn new_arg(arg: &crate::Arg) -> Self { 2719625d8cSopenharmony_ci let ignore_case = arg.is_ignore_case_set(); 2819625d8cSopenharmony_ci Self { 2919625d8cSopenharmony_ci source: None, 3019625d8cSopenharmony_ci indices: Vec::new(), 3119625d8cSopenharmony_ci type_id: Some(arg.get_value_parser().type_id()), 3219625d8cSopenharmony_ci vals: Vec::new(), 3319625d8cSopenharmony_ci raw_vals: Vec::new(), 3419625d8cSopenharmony_ci ignore_case, 3519625d8cSopenharmony_ci } 3619625d8cSopenharmony_ci } 3719625d8cSopenharmony_ci 3819625d8cSopenharmony_ci pub(crate) fn new_group() -> Self { 3919625d8cSopenharmony_ci let ignore_case = false; 4019625d8cSopenharmony_ci Self { 4119625d8cSopenharmony_ci source: None, 4219625d8cSopenharmony_ci indices: Vec::new(), 4319625d8cSopenharmony_ci type_id: None, 4419625d8cSopenharmony_ci vals: Vec::new(), 4519625d8cSopenharmony_ci raw_vals: Vec::new(), 4619625d8cSopenharmony_ci ignore_case, 4719625d8cSopenharmony_ci } 4819625d8cSopenharmony_ci } 4919625d8cSopenharmony_ci 5019625d8cSopenharmony_ci pub(crate) fn new_external(cmd: &crate::Command) -> Self { 5119625d8cSopenharmony_ci let ignore_case = false; 5219625d8cSopenharmony_ci Self { 5319625d8cSopenharmony_ci source: None, 5419625d8cSopenharmony_ci indices: Vec::new(), 5519625d8cSopenharmony_ci type_id: Some( 5619625d8cSopenharmony_ci cmd.get_external_subcommand_value_parser() 5719625d8cSopenharmony_ci .expect(INTERNAL_ERROR_MSG) 5819625d8cSopenharmony_ci .type_id(), 5919625d8cSopenharmony_ci ), 6019625d8cSopenharmony_ci vals: Vec::new(), 6119625d8cSopenharmony_ci raw_vals: Vec::new(), 6219625d8cSopenharmony_ci ignore_case, 6319625d8cSopenharmony_ci } 6419625d8cSopenharmony_ci } 6519625d8cSopenharmony_ci 6619625d8cSopenharmony_ci pub(crate) fn indices(&self) -> Cloned<Iter<'_, usize>> { 6719625d8cSopenharmony_ci self.indices.iter().cloned() 6819625d8cSopenharmony_ci } 6919625d8cSopenharmony_ci 7019625d8cSopenharmony_ci pub(crate) fn get_index(&self, index: usize) -> Option<usize> { 7119625d8cSopenharmony_ci self.indices.get(index).cloned() 7219625d8cSopenharmony_ci } 7319625d8cSopenharmony_ci 7419625d8cSopenharmony_ci pub(crate) fn push_index(&mut self, index: usize) { 7519625d8cSopenharmony_ci self.indices.push(index) 7619625d8cSopenharmony_ci } 7719625d8cSopenharmony_ci 7819625d8cSopenharmony_ci pub(crate) fn vals(&self) -> Iter<Vec<AnyValue>> { 7919625d8cSopenharmony_ci self.vals.iter() 8019625d8cSopenharmony_ci } 8119625d8cSopenharmony_ci 8219625d8cSopenharmony_ci pub(crate) fn into_vals(self) -> Vec<Vec<AnyValue>> { 8319625d8cSopenharmony_ci self.vals 8419625d8cSopenharmony_ci } 8519625d8cSopenharmony_ci 8619625d8cSopenharmony_ci pub(crate) fn vals_flatten(&self) -> Flatten<Iter<Vec<AnyValue>>> { 8719625d8cSopenharmony_ci self.vals.iter().flatten() 8819625d8cSopenharmony_ci } 8919625d8cSopenharmony_ci 9019625d8cSopenharmony_ci pub(crate) fn into_vals_flatten(self) -> Flatten<std::vec::IntoIter<Vec<AnyValue>>> { 9119625d8cSopenharmony_ci self.vals.into_iter().flatten() 9219625d8cSopenharmony_ci } 9319625d8cSopenharmony_ci 9419625d8cSopenharmony_ci pub(crate) fn raw_vals(&self) -> Iter<Vec<OsString>> { 9519625d8cSopenharmony_ci self.raw_vals.iter() 9619625d8cSopenharmony_ci } 9719625d8cSopenharmony_ci 9819625d8cSopenharmony_ci pub(crate) fn raw_vals_flatten(&self) -> Flatten<Iter<Vec<OsString>>> { 9919625d8cSopenharmony_ci self.raw_vals.iter().flatten() 10019625d8cSopenharmony_ci } 10119625d8cSopenharmony_ci 10219625d8cSopenharmony_ci pub(crate) fn first(&self) -> Option<&AnyValue> { 10319625d8cSopenharmony_ci self.vals_flatten().next() 10419625d8cSopenharmony_ci } 10519625d8cSopenharmony_ci 10619625d8cSopenharmony_ci #[cfg(test)] 10719625d8cSopenharmony_ci pub(crate) fn first_raw(&self) -> Option<&OsString> { 10819625d8cSopenharmony_ci self.raw_vals_flatten().next() 10919625d8cSopenharmony_ci } 11019625d8cSopenharmony_ci 11119625d8cSopenharmony_ci pub(crate) fn new_val_group(&mut self) { 11219625d8cSopenharmony_ci self.vals.push(vec![]); 11319625d8cSopenharmony_ci self.raw_vals.push(vec![]); 11419625d8cSopenharmony_ci } 11519625d8cSopenharmony_ci 11619625d8cSopenharmony_ci pub(crate) fn append_val(&mut self, val: AnyValue, raw_val: OsString) { 11719625d8cSopenharmony_ci // We assume there is always a group created before. 11819625d8cSopenharmony_ci self.vals.last_mut().expect(INTERNAL_ERROR_MSG).push(val); 11919625d8cSopenharmony_ci self.raw_vals 12019625d8cSopenharmony_ci .last_mut() 12119625d8cSopenharmony_ci .expect(INTERNAL_ERROR_MSG) 12219625d8cSopenharmony_ci .push(raw_val); 12319625d8cSopenharmony_ci } 12419625d8cSopenharmony_ci 12519625d8cSopenharmony_ci pub(crate) fn num_vals(&self) -> usize { 12619625d8cSopenharmony_ci self.vals.iter().map(|v| v.len()).sum() 12719625d8cSopenharmony_ci } 12819625d8cSopenharmony_ci 12919625d8cSopenharmony_ci // Will be used later 13019625d8cSopenharmony_ci #[allow(dead_code)] 13119625d8cSopenharmony_ci pub(crate) fn num_vals_last_group(&self) -> usize { 13219625d8cSopenharmony_ci self.vals.last().map(|x| x.len()).unwrap_or(0) 13319625d8cSopenharmony_ci } 13419625d8cSopenharmony_ci 13519625d8cSopenharmony_ci pub(crate) fn all_val_groups_empty(&self) -> bool { 13619625d8cSopenharmony_ci self.vals.iter().flatten().count() == 0 13719625d8cSopenharmony_ci } 13819625d8cSopenharmony_ci 13919625d8cSopenharmony_ci pub(crate) fn check_explicit(&self, predicate: &ArgPredicate) -> bool { 14019625d8cSopenharmony_ci if self.source.map(|s| !s.is_explicit()).unwrap_or(false) { 14119625d8cSopenharmony_ci return false; 14219625d8cSopenharmony_ci } 14319625d8cSopenharmony_ci 14419625d8cSopenharmony_ci match predicate { 14519625d8cSopenharmony_ci ArgPredicate::Equals(val) => self.raw_vals_flatten().any(|v| { 14619625d8cSopenharmony_ci if self.ignore_case { 14719625d8cSopenharmony_ci // If `v` isn't utf8, it can't match `val`, so `OsStr::to_str` should be fine 14819625d8cSopenharmony_ci eq_ignore_case(&v.to_string_lossy(), &val.to_string_lossy()) 14919625d8cSopenharmony_ci } else { 15019625d8cSopenharmony_ci OsString::as_os_str(v) == OsStr::new(val) 15119625d8cSopenharmony_ci } 15219625d8cSopenharmony_ci }), 15319625d8cSopenharmony_ci ArgPredicate::IsPresent => true, 15419625d8cSopenharmony_ci } 15519625d8cSopenharmony_ci } 15619625d8cSopenharmony_ci 15719625d8cSopenharmony_ci pub(crate) fn source(&self) -> Option<ValueSource> { 15819625d8cSopenharmony_ci self.source 15919625d8cSopenharmony_ci } 16019625d8cSopenharmony_ci 16119625d8cSopenharmony_ci pub(crate) fn set_source(&mut self, source: ValueSource) { 16219625d8cSopenharmony_ci if let Some(existing) = self.source { 16319625d8cSopenharmony_ci self.source = Some(existing.max(source)); 16419625d8cSopenharmony_ci } else { 16519625d8cSopenharmony_ci self.source = Some(source) 16619625d8cSopenharmony_ci } 16719625d8cSopenharmony_ci } 16819625d8cSopenharmony_ci 16919625d8cSopenharmony_ci pub(crate) fn type_id(&self) -> Option<AnyValueId> { 17019625d8cSopenharmony_ci self.type_id 17119625d8cSopenharmony_ci } 17219625d8cSopenharmony_ci 17319625d8cSopenharmony_ci pub(crate) fn infer_type_id(&self, expected: AnyValueId) -> AnyValueId { 17419625d8cSopenharmony_ci self.type_id() 17519625d8cSopenharmony_ci .or_else(|| { 17619625d8cSopenharmony_ci self.vals_flatten() 17719625d8cSopenharmony_ci .map(|v| v.type_id()) 17819625d8cSopenharmony_ci .find(|actual| *actual != expected) 17919625d8cSopenharmony_ci }) 18019625d8cSopenharmony_ci .unwrap_or(expected) 18119625d8cSopenharmony_ci } 18219625d8cSopenharmony_ci} 18319625d8cSopenharmony_ci 18419625d8cSopenharmony_ciimpl PartialEq for MatchedArg { 18519625d8cSopenharmony_ci fn eq(&self, other: &MatchedArg) -> bool { 18619625d8cSopenharmony_ci let MatchedArg { 18719625d8cSopenharmony_ci source: self_source, 18819625d8cSopenharmony_ci indices: self_indices, 18919625d8cSopenharmony_ci type_id: self_type_id, 19019625d8cSopenharmony_ci vals: _, 19119625d8cSopenharmony_ci raw_vals: self_raw_vals, 19219625d8cSopenharmony_ci ignore_case: self_ignore_case, 19319625d8cSopenharmony_ci } = self; 19419625d8cSopenharmony_ci let MatchedArg { 19519625d8cSopenharmony_ci source: other_source, 19619625d8cSopenharmony_ci indices: other_indices, 19719625d8cSopenharmony_ci type_id: other_type_id, 19819625d8cSopenharmony_ci vals: _, 19919625d8cSopenharmony_ci raw_vals: other_raw_vals, 20019625d8cSopenharmony_ci ignore_case: other_ignore_case, 20119625d8cSopenharmony_ci } = other; 20219625d8cSopenharmony_ci self_source == other_source 20319625d8cSopenharmony_ci && self_indices == other_indices 20419625d8cSopenharmony_ci && self_type_id == other_type_id 20519625d8cSopenharmony_ci && self_raw_vals == other_raw_vals 20619625d8cSopenharmony_ci && self_ignore_case == other_ignore_case 20719625d8cSopenharmony_ci } 20819625d8cSopenharmony_ci} 20919625d8cSopenharmony_ci 21019625d8cSopenharmony_ciimpl Eq for MatchedArg {} 21119625d8cSopenharmony_ci 21219625d8cSopenharmony_ci#[cfg(test)] 21319625d8cSopenharmony_cimod tests { 21419625d8cSopenharmony_ci use super::*; 21519625d8cSopenharmony_ci 21619625d8cSopenharmony_ci #[test] 21719625d8cSopenharmony_ci fn test_grouped_vals_first() { 21819625d8cSopenharmony_ci let mut m = MatchedArg::new_group(); 21919625d8cSopenharmony_ci m.new_val_group(); 22019625d8cSopenharmony_ci m.new_val_group(); 22119625d8cSopenharmony_ci m.append_val(AnyValue::new(String::from("bbb")), "bbb".into()); 22219625d8cSopenharmony_ci m.append_val(AnyValue::new(String::from("ccc")), "ccc".into()); 22319625d8cSopenharmony_ci assert_eq!(m.first_raw(), Some(&OsString::from("bbb"))); 22419625d8cSopenharmony_ci } 22519625d8cSopenharmony_ci} 226