clap/src/mkeymap.rs
2020-05-13 05:53:17 +03:00

163 lines
3.8 KiB
Rust

use crate::{build::Arg, util::Id, INTERNAL_ERROR_MSG};
use std::{
ffi::{OsStr, OsString},
ops::Index,
};
#[derive(PartialEq, Debug, Clone)]
pub(crate) struct Key {
pub(crate) key: KeyType,
pub(crate) index: usize,
}
#[derive(Default, PartialEq, Debug, Clone)]
pub(crate) struct MKeyMap<'b> {
pub(crate) keys: Vec<Key>,
pub(crate) args: Vec<Arg<'b>>,
// FIXME (@CreepySkeleton): this seems useless
built: bool, // mutation isn't possible after being built
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub(crate) enum KeyType {
Short(char),
Long(OsString),
Position(u64),
}
impl KeyType {
pub(crate) fn is_position(&self) -> bool {
match *self {
KeyType::Position(_) => true,
_ => false,
}
}
}
impl PartialEq<&str> for KeyType {
fn eq(&self, rhs: &&str) -> bool {
match self {
KeyType::Long(ref l) => l == OsStr::new(rhs),
_ => false,
}
}
}
impl PartialEq<char> for KeyType {
fn eq(&self, rhs: &char) -> bool {
match self {
KeyType::Short(c) => c == rhs,
_ => false,
}
}
}
impl<'b> MKeyMap<'b> {
//TODO ::from(x), ::with_capacity(n) etc
//? set theory ops?
pub(crate) fn contains<K>(&self, key: K) -> bool
where
KeyType: PartialEq<K>,
{
self.keys.iter().any(|x| x.key == key)
}
pub(crate) fn push(&mut self, value: Arg<'b>) -> usize {
if self.built {
panic!("Cannot add Args to the map after the map is built");
}
let index = self.args.len();
self.args.push(value);
index
}
//TODO ::push_many([x, y])
pub(crate) fn insert_key(&mut self, key: KeyType, index: usize) {
if index >= self.args.len() {
panic!("Index out of bounds");
}
self.keys.push(Key { key, index });
}
//TODO ::insert_keyset([Long, Key2])
// ! Arg mutation functionality
pub(crate) fn get(&self, key: &KeyType) -> Option<&Arg<'b>> {
self.keys
.iter()
.find(|k| k.key == *key)
.map(|k| &self.args[k.index])
}
//TODO ::get_first([KeyA, KeyB])
pub(crate) fn is_empty(&self) -> bool {
self.keys.is_empty() && self.args.is_empty()
}
pub(crate) fn _build(&mut self) {
self.built = true;
for (i, arg) in self.args.iter_mut().enumerate() {
for k in _get_keys(arg) {
self.keys.push(Key { key: k, index: i });
}
}
}
//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(crate) fn remove_by_name(&mut self, name: &Id) -> Option<Arg<'b>> {
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))
}
}
impl<'b> Index<&'_ KeyType> for MKeyMap<'b> {
type Output = Arg<'b>;
fn index(&self, key: &'_ KeyType) -> &Self::Output {
self.get(key).expect(INTERNAL_ERROR_MSG)
}
}
fn _get_keys(arg: &Arg) -> Vec<KeyType> {
if let Some(index) = arg.index {
return vec![KeyType::Position(index)];
}
let mut keys = vec![];
for short in arg.short_aliases.iter().map(|(c, _)| KeyType::Short(*c)) {
keys.push(short);
}
if let Some(c) = arg.short {
keys.push(KeyType::Short(c));
}
for long in arg
.aliases
.iter()
.map(|(a, _)| KeyType::Long(OsString::from(a)))
{
keys.push(long);
}
if let Some(long) = arg.long {
keys.push(KeyType::Long(OsString::from(long)));
}
keys
}