clap/src/mkeymap.rs

371 lines
9.6 KiB
Rust
Raw Normal View History

use crate::build::Arg;
2018-08-28 01:44:09 +00:00
use std::ffi::{OsStr, OsString};
2018-11-14 00:44:43 +00:00
type Id = u64;
2018-11-14 00:44:43 +00:00
#[derive(PartialEq, Debug, Clone)]
pub struct Key {
pub key: KeyType,
2018-11-14 17:05:06 +00:00
pub index: usize,
2018-11-14 00:44:43 +00:00
}
2018-07-19 12:50:47 +00:00
2018-07-26 15:15:47 +00:00
#[derive(Default, PartialEq, Debug, Clone)]
pub struct MKeyMap<'b> {
2018-11-14 00:44:43 +00:00
pub keys: Vec<Key>,
pub args: Vec<Arg<'b>>,
2018-08-28 00:25:37 +00:00
built: bool, // mutation isn't possible after being built
2018-07-19 12:50:47 +00:00
}
2020-02-05 10:04:59 +00:00
#[doc(hidden)]
2018-07-19 12:50:47 +00:00
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
2018-07-29 18:20:17 +00:00
pub enum KeyType {
2018-07-19 12:50:47 +00:00
Short(char),
2018-07-29 18:20:17 +00:00
Long(OsString),
2018-08-01 15:33:55 +00:00
Position(u64),
2018-07-19 12:50:47 +00:00
}
2018-08-21 00:23:52 +00:00
impl KeyType {
pub(crate) fn is_position(&self) -> bool {
match *self {
KeyType::Position(_) => true,
_ => false,
}
}
}
2018-11-14 00:44:43 +00:00
impl PartialEq<&str> for KeyType {
fn eq(&self, rhs: &&str) -> bool {
match self {
KeyType::Long(ref l) => l == OsStr::new(rhs),
2018-11-14 17:05:06 +00:00
_ => false,
2018-11-14 00:44:43 +00:00
}
}
}
impl PartialEq<char> for KeyType {
fn eq(&self, rhs: &char) -> bool {
match self {
KeyType::Short(c) => c == rhs,
2018-11-14 17:05:06 +00:00
_ => false,
2018-11-14 00:44:43 +00:00
}
}
}
impl<'b> MKeyMap<'b> {
2020-01-31 09:13:44 +00:00
pub fn new() -> Self {
MKeyMap::default()
}
2018-07-19 12:50:47 +00:00
//TODO ::from(x), ::with_capacity(n) etc
//? set theory ops?
#[deprecated(since = "3.0.0", note = "Use `contains` instead")]
2020-01-31 09:13:44 +00:00
pub fn contains_long(&self, l: &str) -> bool {
self.contains(l)
}
#[deprecated(since = "3.0.0", note = "Use `contains` instead")]
2020-01-31 09:13:44 +00:00
pub fn contains_short(&self, c: char) -> bool {
self.contains(c)
}
2018-11-14 00:44:43 +00:00
pub fn contains<K>(&self, key: K) -> bool
where
KeyType: PartialEq<K>,
{
self.keys.iter().any(|x| x.key == key)
}
2018-11-14 00:44:43 +00:00
pub fn insert(&mut self, key: KeyType, value: Arg<'b>) -> usize {
2018-07-19 12:50:47 +00:00
let index = self.push(value);
2018-11-14 00:44:43 +00:00
self.keys.push(Key { key, index });
2018-07-19 12:50:47 +00:00
index
}
pub fn push(&mut self, value: Arg<'b>) -> usize {
2018-08-28 00:25:37 +00:00
if self.built {
panic!("Cannot add Args to the map after the map is built");
2018-07-19 12:50:47 +00:00
}
2018-07-24 16:48:24 +00:00
2018-11-14 00:44:43 +00:00
let index = self.args.len();
self.args.push(value);
2018-08-28 00:25:37 +00:00
2018-07-19 14:27:25 +00:00
index
2018-07-19 12:50:47 +00:00
}
//TODO ::push_many([x, y])
2018-07-29 18:20:17 +00:00
pub fn insert_key(&mut self, key: KeyType, index: usize) {
2018-11-14 00:44:43 +00:00
if index >= self.args.len() {
2018-07-19 12:50:47 +00:00
panic!("Index out of bounds");
}
2018-11-14 17:05:06 +00:00
self.keys.push(Key { key, index });
2018-07-19 12:50:47 +00:00
}
//TODO ::insert_keyset([Long, Key2])
2018-07-24 16:48:24 +00:00
// ! Arg mutation functionality
pub fn get(&self, key: &KeyType) -> Option<&Arg<'b>> {
self.keys
.iter()
.find(|k| k.key == *key)
.map(|k| &self.args[k.index])
2018-07-19 12:50:47 +00:00
}
2018-11-14 00:44:43 +00:00
//TODO ::get_first([KeyA, KeyB])
2018-07-19 12:50:47 +00:00
pub fn get_mut(&mut self, key: &KeyType) -> Option<&mut Arg<'b>> {
let key = self.keys.iter().find(|k| k.key == *key);
2019-11-11 11:54:55 +00:00
match key {
Some(k) => self.args.get_mut(k.index),
None => None,
}
2019-11-11 11:54:55 +00:00
}
2020-01-31 09:13:44 +00:00
pub fn is_empty(&self) -> bool {
self.keys.is_empty() && self.args.is_empty()
}
2018-08-28 01:44:09 +00:00
2018-11-14 17:12:34 +00:00
pub fn remove_key(&mut self, key: &KeyType) {
self.keys
.iter()
.position(|k| k.key == *key)
.map(|i| self.keys.swap_remove(i));
2018-07-19 12:50:47 +00:00
}
2018-07-19 14:27:25 +00:00
2018-08-01 15:33:55 +00:00
pub fn insert_key_by_name(&mut self, key: KeyType, name: &str) {
let index = self.find_by_name(name);
2018-11-14 17:05:06 +00:00
self.keys.push(Key { key, index });
2018-08-01 15:33:55 +00:00
}
2018-08-28 00:25:37 +00:00
pub fn _build(&mut self) {
self.built = true;
2018-08-01 15:33:55 +00:00
2018-11-14 00:44:43 +00:00
for (i, arg) in self.args.iter_mut().enumerate() {
2018-08-28 00:25:37 +00:00
for k in _get_keys(arg) {
2018-11-14 17:05:06 +00:00
self.keys.push(Key { key: k, index: i });
2018-08-28 00:25:37 +00:00
}
}
2018-08-01 15:33:55 +00:00
}
pub fn make_entries_by_index(&mut self, index: usize) {
let short;
let positional;
2018-11-14 17:12:34 +00:00
let mut longs: Vec<_>;
2018-08-01 15:33:55 +00:00
{
2018-11-14 00:44:43 +00:00
let arg = &self.args[index];
2018-11-14 17:12:34 +00:00
short = arg.short.map(KeyType::Short);
positional = arg.index.map(KeyType::Position);
2018-08-01 15:33:55 +00:00
longs = arg
.aliases
.clone()
.map(|v| {
v.iter()
.map(|(n, _)| KeyType::Long(OsString::from(n)))
.collect()
2018-11-14 17:05:06 +00:00
})
2018-11-14 17:12:34 +00:00
.unwrap_or_default();
2018-08-01 15:33:55 +00:00
longs.extend(arg.long.map(|l| KeyType::Long(OsString::from(l))));
}
2018-11-14 18:36:12 +00:00
if let Some(s) = short {
self.insert_key(s, index)
}
if let Some(p) = positional {
self.insert_key(p, index)
}
2018-08-01 15:33:55 +00:00
}
pub fn find_by_name(&mut self, name: &str) -> usize {
2018-11-14 00:44:43 +00:00
self.args
2018-08-01 15:33:55 +00:00
.iter()
.position(|x| x.name == name)
.expect("No such name found")
}
2018-08-28 00:25:37 +00:00
pub fn remove(&mut self, key: &KeyType) -> Option<Arg<'b>> {
2018-08-28 00:25:37 +00:00
if self.built {
panic!("Cannot remove args after being built");
}
let idx = self.keys.iter().position(|k| k.key == *key);
2018-11-14 00:44:43 +00:00
if let Some(idx) = idx {
let arg = self.args.swap_remove(idx);
for key in _get_keys(&arg) {
2019-04-05 20:05:19 +00:00
self.remove_key(&key);
2018-11-14 00:44:43 +00:00
}
return Some(arg);
2018-08-28 00:25:37 +00:00
}
2018-11-14 00:44:43 +00:00
None
2018-08-28 00:25:37 +00:00
}
2018-11-14 00:44:43 +00:00
2018-08-28 00:25:37 +00:00
//TODO ::remove_many([KeyA, KeyB])
//? probably shouldn't add a possibility for removal?
//? or remove by replacement by some dummy object, so the order is preserved
pub fn remove_by_name(&mut self, _name: Id) -> Option<Arg<'b>> {
2018-08-28 00:25:37 +00:00
if self.built {
panic!("Cannot remove args after being built");
}
self.args
.iter()
.position(|arg| arg.id == _name)
.map(|i| self.args.swap_remove(i))
2018-08-28 00:25:37 +00:00
}
2018-08-01 15:33:55 +00:00
}
2018-11-14 00:44:43 +00:00
fn _get_keys(arg: &Arg) -> Vec<KeyType> {
if let Some(index) = arg.index {
return vec![KeyType::Position(index)];
}
2018-07-19 12:50:47 +00:00
2018-11-14 00:44:43 +00:00
let mut keys = vec![];
if let Some(c) = arg.short {
keys.push(KeyType::Short(c));
}
if let Some(ref aliases) = arg.aliases {
for long in aliases
.iter()
.map(|(a, _)| KeyType::Long(OsString::from(a)))
{
keys.push(long);
2018-07-19 14:27:25 +00:00
}
2018-07-19 12:50:47 +00:00
}
2018-11-14 00:44:43 +00:00
if let Some(long) = arg.long {
keys.push(KeyType::Long(OsString::from(long)));
}
keys
2018-07-19 12:50:47 +00:00
}
#[cfg(test)]
mod tests {
2018-07-19 14:27:25 +00:00
use self::KeyType::*;
2018-07-19 12:50:47 +00:00
use super::*;
#[test]
fn get_some_value() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
2018-07-24 16:48:24 +00:00
assert_eq!(
2018-11-14 17:12:34 +00:00
map.get(&Long(OsString::from("One"))),
2018-07-24 16:48:24 +00:00
Some(&Arg::with_name("Value1"))
);
2018-07-19 12:50:47 +00:00
}
#[test]
fn get_none_value() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-11-14 17:12:34 +00:00
map.get(&Long(OsString::from("Two")));
2018-07-24 16:48:24 +00:00
2018-11-14 17:12:34 +00:00
assert_eq!(map.get(&Long(OsString::from("Two"))), None);
2018-07-19 12:50:47 +00:00
}
// #[test]
// fn insert_delete_value() {
// let mut map = MKeyMap::new();
// map.insert("One", clap::Arg::with_name("Value1"));
// assert_eq!(map.remove("One"), Some(clap::Arg::with_name("Value1")));
// assert!(map.is_empty());
// }
#[test]
fn insert_duplicate_key() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
assert_eq!(
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value2")),
2018-07-19 12:50:47 +00:00
1
);
}
#[test]
// #[should_panic(expected = "Len changed")]
2018-07-19 12:50:47 +00:00
fn insert_duplicate_value() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
2018-11-14 00:44:43 +00:00
let orig_len = map.args.len();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("Two")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
assert_eq!(map.args.len(), orig_len + 1 /* , "Len changed" */);
// assert_eq!(
// map.get(&Long(OsString::from("One"))),
// map.get(&Long(OsString::from("Two")))
// );
2018-07-19 12:50:47 +00:00
}
// #[test]
// fn insert_delete_none() {
// let mut map = MKeyMap::new();
// map.insert("One", clap::Arg::with_name("Value1"));
// assert_eq!(map.remove("Two"), None);
// assert!(!map.is_empty());
// assert_eq!(map.get("One"), Some(clap::Arg::with_name("Value1")));
// }
#[test]
fn insert_multiple_keys() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-29 18:20:17 +00:00
let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert_key(Long(OsString::from("Two")), index);
2018-07-19 12:50:47 +00:00
assert_eq!(
2018-11-14 17:12:34 +00:00
map.get(&Long(OsString::from("One"))),
map.get(&Long(OsString::from("Two")))
2018-07-19 12:50:47 +00:00
);
2018-11-14 00:44:43 +00:00
assert_eq!(map.args.len(), 1);
2018-07-19 12:50:47 +00:00
}
2018-07-19 14:27:25 +00:00
2018-07-29 18:20:17 +00:00
// #[test]
// fn insert_by_name() {
// let mut map: MKeyMap<Arg> = MKeyMap::new();
// let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
// map.insert_key_by_name(Long(OsString::from("Two")), "Value1");
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
// assert_eq!(
// map.get(Long(OsString::from("One"))),
// map.get(Long(OsString::from("Two")))
// );
// assert_eq!(map.values.len(), 1);
// }
2018-07-19 12:50:47 +00:00
#[test]
2018-07-19 14:27:25 +00:00
fn get_mutable() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
assert_eq!(
2018-11-14 17:12:34 +00:00
map.get_mut(&Long(OsString::from("One"))),
2018-07-24 16:48:24 +00:00
Some(&mut Arg::with_name("Value1"))
2018-07-19 14:27:25 +00:00
);
2018-07-19 12:50:47 +00:00
}
#[test]
fn remove_key() {
2018-11-14 00:44:43 +00:00
let mut map: MKeyMap = MKeyMap::new();
2018-07-29 18:20:17 +00:00
let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
2018-07-19 12:50:47 +00:00
2018-07-29 18:20:17 +00:00
map.insert_key(Long(OsString::from("Two")), index);
2018-11-14 17:12:34 +00:00
map.remove_key(&Long(OsString::from("One")));
2018-07-19 12:50:47 +00:00
assert_eq!(map.keys.len(), 1);
2018-11-14 00:44:43 +00:00
assert_eq!(map.args.len(), 1);
2018-07-19 12:50:47 +00:00
}
}